Redes de computadores II Comunicação entre processos Prof. Diovani Milhorim Comunicação entre processos Troca de mensagens Sockets (cliente/servidor) RPC (remote procedure call) Comunicação entre processos Troca de mensagens Síncrona Assíncrona Unidirecional Bidirecional Comunicação entre processos Troca de mensagens unidirecional A comunicação de dados entre processos é chamada de unidirecional quando um dos processos sempre envia mensagens para um outro processo. Comunicação entre processos Troca de mensagens bidirecional A comunicação de dados entre processos é chamada de bidirecional quando qualquer um dos processos pode enviar ou receber mensagens entre eles. Comunicação entre processos Troca de mensagens Podemos definir duas entidades na troca de mensagens: Emissor Receptor Comunicação entre processos Troca de mensagens Emissor : Entidade que envia as mensagens. No caso de comunicação bidirecional o processo pode assumir tanto o papel de emissor quanto de receptor. No caso de comunicação unidirecional, um processo sempre será emissor e outro sempre o receptor. Comunicação entre processos Troca de mensagens síncrona Na comunicação síncrona, o processo emissor fica suspenso esperando que o receptor receba a mensagem. É comum que continue bloqueado até réplica do receptor Comunicação entre processos Troca de mensagens síncrona Não existe necessidade de bufferização Não existe necessidade de mecanismo extra para sincronizar. Maior risco de deadlock. Comunicação entre processos Troca de mensagens assíncrona Os processos nunca ficam bloqueados. Um processo A envia mensagem para o processo B e continua o seu processamento normalmente. O receptor, na hora que desejar ler a mensagem, realiza sua recepção e também continua seu processamento normal. Comunicação entre processos Troca de mensagens assíncrona Existência de bufferização Ausência de bloqueios Inexistência de deadlocks. Maior modularidade e escalabilidade de aplicativos. Ausência de sincronismo. Comunicação entre processos Estrutura de comunicação entre processos. Pipes: Funcionam com tubulações, o que se coloca de um lado segue sequencialmente para o outro lado. Pipes anônimos. Pipes nomeados. Comunicação entre processos Estrutura de comunicação entre processos. Pipes anônimos. Mecanismo arcaico de comunicação entre processos. É sempre unidirecional, local, e síncrono. Ex. Comandos em seqüência do bash. Comunicação entre processos Estrutura de comunicação entre processos. Pipes anônimos. Permite apenas comunicação unidirecional. Se um processo está tentando passar os dados, e o leitor ainda não está pronto, o pipe bloqueia o processo até que o mesmo esteja disponível. Sendo assim, o próprio pipe provê a sincronização dos processos. Os pipes só podem se comunicar entre processos “parent – child”, por exemplo, comandos executados em um mesmo terminal. Ex : cat /etc/passwd | more Comunicação entre processos Estrutura de comunicação entre processos. Pipes nomeados. Um pipe nomeado é uma extensão do pipe convencional. A diferença é que um pipe termina juntamente com o fim da execução do programa, e um pipe nomeado deve ser criado e destruido explicitamente. Para criar um pipe nomeado pode-se usar o comando mknod ou mkfifo. Pode-se usar pipes nomeados em programas para prover meios de comunicação inter processos. É bidirecional, local ou remoto. Pode ser síncrono ou assíncrono. Diversas instâncias de um pipe podem ser criadas, uma para cada cliente. Ex. em bash : #mknod ou mkfifo Comunicação entre processos Pipes nomeados. Exemplo: #mkfifo teste #cat < teste O pipe fica esperando até obter algum dado Em outro terminal execute: #ls > teste A saída do comando ls será redirecionada para o pipe nomeado “teste” Desta forma, a saída do comando ls será ecoada no primeiro terminal, o qual aguardava recebimento de dados no pipe. Comunicação entre processos Sockets: Uma interface local, criada e possuida pelas aplicações, controlada pelo S.O. atráves do qual os processos podem trocar mensagens. Comunicação entre processos Sockets: Comunicação entre processos que se utiliza das funcionalidades dos protocolos de rede para realizar a troca de informações entre emissor e receptor. Comunicação entre processos Sockets: A programação por portas (sockets) se utiliza dos serviços de redes, sejam eles orientados ou não orientados a conexão. Comunicação entre processos Sockets: Interface padrão para comunicação entre processos em redes TCP/IP Nasceu com o Unix de Berkeley Os projetistas tentaram usar ao máximo as chamadas de sistema do Unix Implementada hoje em vários Sos Programar com sockets pode ser visto como desenvolver um protocolo de aplicação Comunicação entre processos Sockets: Um socket pode ser entendido como uma porta de um canal de comunicação que permite a um processo executando em um computador enviar/receber mensagens para/de outro processo que pode estar sendo executado no mesmo computador ou num computador remoto. Comunicação entre processos Sockets: Abaixo temos uma figura com que representa a comunicação de sockets e a pilha TCP/IP Comunicação entre processos Sockets: Comunicação entre processos Sockets: Comunicação entre processos Sockets: Comunicação entre processos Sockets: Os sockets permitem então a comunicação processo a processo da seguinte forma : comunicação local : processos locais usando sockets locais comunicação remota : processos remotos usando sockets em rede (TCP/IP) Comunicação entre processos Sockets: Tipos de serviço de transporte: Datagrama - transporte não orientado a conexão e sem controle de erros ( protocolo UDP) DataStream - transporte orientado a conexão com controle de erros ( protocolo TCP ) Raw – baixo nível – pacotes IP Comunicação entre processos Sockets: Serviço com conexão Serviço sem conexão Implementa um stream de dados (SOCK_STREAM) Protocolo TCP (tipicamente) Implementa um serviço de datagramas (SOCK_DGRAM) Protocolo UDP (tipicamente) Acessa diretamente a camada de rede (SOCK_RAW) Serviço de baixo nível Protocolo IP (tipicamente) Comunicação entre processos Sockets: Principais funções da API socket connect write read close bind listen Cria um novo descritor para comunicação Iniciar conexão com servidor Escreve dados em uma conexão Lê dados de uma conexão Fecha a conexão Atribui um endereço IP e uma porta a um socket Coloca o socket em modo passivo, para “escutar” portas Bloqueia o servidor até chegada de requisição de accept conexão recvfrom Recebe um datagrama e guarda o endereço do emissor Envia um datagrama especificando o endereço sendto Comunicação entre processos Sockets: Aplicação cliente-servidor usando serviços de transporte orientado a conexão servidor cliente criar porta para requisitante Esperar pela requisição entrante Criar porta – Conectar no servidor Enviar requisição usando o socket criado cria socket de comunicação ler requisição do socket de conexão Escrever resposta para o socket de conexão Ler resposta do servidor Fechar o socket Fechar socket Comunicação entre processos Servidor Sockets: orientado a conexão (tcp) socket () bind () listen () accept () bloqueado Cliente socket () connect () write () read () write () close () read () close () Comunicação entre processos Sockets: orientado a conexão (tcp) – estrutura típica do servidor Comunicação entre processos Sockets: Programação C/C++ C é a linguagem “básica” para programação com sockets De maneira diferente de Java, programar com sockets em C/C++ envolve utilizar todas as chamadas da API Comunicação entre processos #include ... #include <sys/socket.h> int main(int argc, char **argv) { int s; struct sockaddr_in dest; char msg_write[100], msg_read[100]; s = socket(AF_INET, SOCK_STREAM, 0)); bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(9999); inet_aton(“127.0.0.1”, &dest.sin_addr.s_addr); connect(s, (struct sockaddr*)&dest, sizeof(dest)); do { scanf("%s",msg_write); write (s, msg_write, strlen(msg_write)+1); read (s, msg_read, MAXBUF); } while (strcmp(msg_read,"bye")); close(s); } Comunicação entre processos #include ... #include <sys/socket.h> int main(int argc, char **argv) { int s, client_s; struct sockaddr_in self, client; int addrlen = sizeof(client); char msg_write[100], msg_read[100]; s = socket(AF_INET, SOCK_STREAM, 0); bzero(&self, sizeof(self)); self.sin_family = AF_INET; self.sin_port = htons(9999); self.sin_addr.s_addr = INADDR_ANY; bind(s, (struct sockaddr*)&self, sizeof(self)); listen(s, 5); while (1) { client_s = accept(s, (struct sockaddr*)&client, &addrlen); do { read (client_s, msg_read, MAXBUF); write (client_s, msg_read, strlen(msg_read)+1); } while (strcmp(msg_read,"bye")); close(client_s); } } Comunicação entre processos Sockets: Programação Java Java modernizou a API para trabalhar com sockets O programador não precisa chamar todas as funções, algumas chamadas são automáticas Exemplos Socket: equivalente a socket e bind ServerSocket: equivalente a socket, bind e listen Sockets são implementados no pacote java.net A transmissão e o envio de dados são feitos através de classes do pacote java.io de maneira semelhante à escrita e leitura em arquivos Classes DataInputStream, DataOutputStream, etc., Comunicação entre processos Sockets: Exemplo:cliente clienteJava (TCP) Java (TCP) import java.io.*; import java.net.*; class TCPClient { public static void main(String argv[]) throws Exception { String sentence; String modifiedSentence; BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); Socket clientSocket = new Socket("hostname", 6789); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStr eam()); BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream() )); sentence = inFromUser.readLine(); outToServer.writeBytes(sentence + '\n'); modifiedSentence = inFromServer.readLine(); System.out.println ("FROM SERVER: " + modifiedSentence ); clientSocket.close(); }} Comunicação entre processos Exemplo:servidor servidor.Java (TCP) Java (TCP) import java.io.*; import java.net.*; class TCPServer { public static void main(String argv[]) throws Exception { String clientSentence; String capitalizedSentence; ServerSocket welcomeSocket = new ServerSocket(6789); while(true) { Socket connectionSocket = welcomeSocket.accept(); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInp utStream())); DataOutputStream outToClient = new DataOutputStream (connectionSocket.getOutputStream()); clientSentence = inFromClient.readLine(); capitalizedSentence = clientSentence.toUpperCase() + '\n'; outToClient.writeBytes(capitalizedSentence); } } } Comunicação entre processos Sockets: Aplicação cliente-servidor usando serviços de transporte não orientado a conexão servidor cliente criar porta para requisitante Criar porta (datagrama) Enviar requisição para servidor Especificando endereço do servidor e número da porta ler requisição do socket de conexão Escrever resposta para o socket de conexão Especificando endereço do cliente e número da porta Ler resposta do servidor Fechar socket Comunicação entre processos Servidor Sockets: não orientado conexão (udp) socket () bind () recvfrom () bloqueado Cliente socket () sendto () sendto () close () recvfrom () close () Comunicação entre processos Cliente java UDP import java.io.*; import java.net.*; class UDPClient { public static void main(String args[]) throws Exception { BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("hostname"); byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024]; String sentence = inFromUser.readLine(); sendData = sentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); } } Comunicação entre processos Serrvidor java.udp import java.io.*; import java.net.*; class UDPServer { public static void main(String args[]) throws Exception { DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; byte[] sendData = new byte[1024]; while(true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivePacket.getAddress(); int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); sendData = capitalizedSentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); } } }