Baixe o app para aproveitar ainda mais
Prévia do material em texto
Programação Paralela e Distribuída 05 - Primitivas de sistemas distribuídos Prof. Laerte M. Rodrigues laerte.rodrigues@ifmg.edu.br Sistemas distribuídos I São sistemas que são executados em diversas máquinas distintas ligadas por uma rede I Aplicações distribuídas I Skype I Internet I Sistemas bancários I Podem ter diferentes estruturas físicas I Internet: Vários computadores (pessoais e empresariais) conectados entre si por uma ISP (Internet Service Provider) I Clusters: Diferentes máquinas interconectadas por uma rede local Sistemas distribuídos I Vantagens I Distribui a carga de trabalho entre si I Podem suportar um conjunto de tarefas maior (tanto em quantidade como na carga de trabalho) I Permite o compartilhamento de dados e recursos I Desvantagens e dificuldades I Acomplamento fraco (Máquinas trocam dado por rede, logo, tempo de comunicação é limitado) I Não determinístico (Comportamento pouco previsível) I Pode existir sobrecarga/congestionamento da rede I Não é possível garantir sincronia entre as máquinas I S.O. e máquinas diferentes Sistemas distribuídos I Não é possível sincronização de tempo global I Impossível ter uma visão global de transações I Acesso concorrente à dados e recursos (passível de deadlock) I Máquinas dispersas na rede I Sujeito a diversos tipos de falha Controle da camada de rede I O protocolo IP é feito num estrutura de dados chamada sockaddr_in I Está declarada na header arpa/inet.h I Possui as informações de endereço IP e porta I Os 3 atributos que devem ser tratados nela são I sin_family: Qual o domínio será utilizado (o mesmo da camada de transporte) I sin_port: Número da porta que será utilizada (deve-se utilizar a função htons para converter o inteiro no formato de 16 bits) I sin_addr.s_addr: Endereço IP no formato Big Endian Controle da camada de rede I Deve-se utilizar a função inet_addr para transformar um IP ou hostname no formato IP big endian I Pode-se utilizar também a função htonl(INADDR_ANY) para indicar que o servidor irá receber informação de qualquer endereço IP Sockets I Recurso do S.O. para troca de informação entre computadores pela rede I Disponibiliza recursos para receber e encanminhar dados (IP) bem como o tipo da conexão que será feita (TCP/UDP) I Responsável por receber/enviar os pacotes de dados na rede I No modelo OSI temos então I Camada de aplicação (Solução a ser desenvolvida) I Camada de transporte (TCP/UDP) I Camada de rede (IP) Sockets I A biblioteca sys/socket.h possui os elementos para conexão com outros hosts pela rede I int socket(int domain, int type, int protocol) I int domain: Indica qual será o ptrocolo de rede utilizado, podemos usar AF_INET, AF_INET6 (IPv4 e IPv6 respectivamente) I int type: O tipo de comunicação que será feito pelo socket podendo ser SOCK_STREAM (TCP) e SOCK_DGRAM (UDP) I int protocol: Normalmente implicito (valor default 0) I O mesmo retornará um descritor de arquivo, -1 se houver falha I A biblioteca unistd.h têm a função close que pode ser usado para o socket Demais funções de sockets I bind: Vincula o socket à um endereço IP, necessário para a conexão se tornar visível I int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); I sockfd: Descritor de arquivo do socket I addr: Endereço IP construído I addrlen: Tamanho da estrutura de endereçamento IP (utilize sizeof(sockaddr_in)) I Retorna 0 para sucesso, -1 caso contrário I listen: Marca um socket como passível para que o mesmo possa ficar “ouvindo” uma porta para receber uma conexão (aceito apenas para o protocolo TCP) Demais funções de sockets I int listen(int sockfd, int backlog); I socfd: Descritor de arquivo do socket I backlog: Quantidade máxima de conexões pendentes que o servidor irá suportar I Retorna 0 para sucesso, -1 caso contrário I accept: Cria uma conexão vinda do socket passivo (do listen) I int accept(int sockfd, const struct sockaddr *addr, socklen_t addrlen); I sockfd: Descritor de arquivo do socket I addr: Endereço IP construído I addrlen: Tamanho da estrutura de endereçamento IP (utilize sizeof(sockaddr_in)) Transmissão de dados I Com a(s) conexão(ões) estabelecidas os dados podem ser enviados e recebidos a partir dos sockets pelas funções send e recv I A função sendto envia um pacote de dados para outra máquina I ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); I sockfd: Descritor de arquivo do socket I buf: Buffer a ser enviado I len: Tamanho do buffer (em bytes) Transmissão de dados I flags: Indica o comportamento da mensagem podendo ser 0 (default) ou indicando que existem mais dados a serem enviados (MSG_MORE) I dest_addr: Endereço IP do destinatário I addrlen: Tamanho do endereço I A função retorna quantidade de bytes enviados I A função recvfrom recebe um dado da rede I ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); I sockfd: Descritor de arquivo do socket I buf: Buffer a ser enviado I len: Tamanho do buffer (em bytes) I flags: Indica o comportamento da mensagem podendo ser 0 (default) ou indicando que existem mais dados a serem enviados (MSG_MORE) Transmissão de dados I src_addr: Endereço IP do remetente I addrlen: Tamanho do endereço I A função retorna quantidade de bytes recebidos Socket com UDP I Estrutura de pacote utilizados pela UDP I Não existe compromisso de integridade I Utilizado por servidores DNS I O servidor que se utiliza de UDP necessita apenas se preocupar em receber a mensagem Socket com UDP I1 #include <sys/socket.h> 2 #include <arpa/inet.h> 3 #include <iostream > 4 #include <cstring > 5 6 #define MSG_SIZE 255 7 8 using namespace std; 9 10 int main(int argc , char **argv) { 11 // Construção do socket 12 int sck = socket(PF_INET ,SOCK_DGRAM ,0); 13 14 // Endereçamento IP (O Servidor aceita conexão de qualquer host) 15 sockaddr_in addr_server; 16 addr_server.sin_family = AF_INET; 17 addr_server.sin_port = htons (80); 18 addr_server.sin_addr.s_addr = htonl(INADDR_ANY); Socket com UDP 19 20 // Tamanho do endereço 21 socklen_t addr_server_len = sizeof(addr_server); 22 23 // Variáveis do IP remente 24 sockaddr_in addr_from; 25 socklen_t addr_from_len; 26 27 // Faz o bind da porta 28 if(bind(sck ,(const sockaddr *) &addr_server ,addr_server_len) 29 == -1) { 30 cout << "Erro no bind" << endl; 31 exit (0); 32 } 33 34 // Laço infinito do servidor 35 while (1) { 36 // Buffer da mensagem recebida Socket com UDP 37 char str[MSG_SIZE ]; 38 39 recvfrom(sck ,str ,MSG_SIZE ,0, 40 (sockaddr *)&addr_from ,& addr_from_len); 41 cout << "Mensagem recebida: " << str << endl; 42 bzero(str ,MSG_SIZE); 43 } 44 45 return 0; 46 } I O cliente se preocupa apenas em enviar o pacote Socket com UDP I1 #include <sys/socket.h> 2 #include <arpa/inet.h> 3 #include <iostream > 4 #include <cstring > 5 6 #define MSG_SIZE 255 7 8 using namespace std; 9 10 int main(int argc , char **argv) { 11 // Construção do socket 12 int sck = socket(PF_INET ,SOCK_DGRAM ,0); 13 14 // Endereçamento IP 15 // (O primeiro argumento do executavel sera o host) 16 sockaddr_in addr_server; 17 addr_server.sin_family = AF_INET; 18 addr_server.sin_port = htons (9999); Socket com UDP 19 addr_server.sin_addr.s_addr = inet_addr(argv [1]); 20 21 // Tamanho do endereço 22 socklen_t addr_server_len = sizeof(addr_server); 23 24 cout << "Digite a mensagem a ser enviada ao servidor "; 25 cout << "(! finaliza)" << endl; 26 27 // Laço infinito do servidor 28 while (1) { 29 // Buffer da mensagem a ser enviada 30 string str; 31 32 cout << ">"; 33 getline(cin ,str); 34 35 if(str == "!") { 36 break; Socket com UDP37 } 38 39 sendto(sck ,str.c_str(),str.length () ,0, 40 (sockaddr *) &addr_server ,addr_server_len); 41 } 42 43 return 0; 44 } Socket com TCP I Conexão utilizando o protocolo TCP I A conexão deve ser mantida pelas 2 máquinas I O servidor pode “aceitar” ou não a conexão do cliente I A conexão é mantida até uma das pontas desligar I O processo do servidor é mais complexo I Ao ouvir uma porta (listen) o servidor ficará experando uma conexão (accept) Socket com TCP 1 #include <sys/socket.h> 2 #include <arpa/inet.h> 3 #include <unistd.h> 4 #include <iostream > 5 #include <cstring > 6 7 #define MAX_QUEUE 2 8 #define MSG_SIZE 255 9 10 using namespace std; 11 12 int main(int argc , char **argv) { 13 // Construção do socket 14 int sck_server = socket(PF_INET ,SOCK_STREAM ,0); 15 16 // Endereçamento IP (O Servidor aceita conexão de qualquer host) 17 sockaddr_in addr_server; 18 addr_server.sin_family = AF_INET; Socket com TCP 19 addr_server.sin_port = htons (9999); 20 addr_server.sin_addr.s_addr = htonl(INADDR_ANY); 21 22 // Tamanho do endereço 23 socklen_t addr_server_len = sizeof(addr_server); 24 25 // Variáveis do IP remente 26 sockaddr_in addr_from; 27 socklen_t addr_from_len; 28 29 // Faz o bind da porta 30 if(bind(sck_server ,(const sockaddr *) &addr_server ,addr_server_len) 31 == -1) { 32 cout << "Erro no bind" << endl; 33 exit (0); 34 } 35 36 // Define que o bind suporta até 10 conexões na fila Socket com TCP 37 if(listen(sck_server ,MAX_QUEUE) == -1) { 38 cout << "Erro ao ouvir a porta" << endl; 39 exit (0); 40 } 41 42 while (1) { 43 int sck_client = accept(sck_server ,( sockaddr *)&addr_from ,& addr_from_len); 44 char str[MSG_SIZE ]; 45 46 if(sck_client < 0) { 47 cout << "Erro ao aceitar conexão do cliente" << endl; 48 exit (0); 49 } 50 51 // Espera mensagem do cliente 52 bzero(str ,MSG_SIZE); 53 recvfrom(sck_client ,str ,MSG_SIZE ,0, 54 (sockaddr *)&addr_from ,& addr_from_len); Socket com TCP 55 cout << "Mensagem recebida: " << str << endl; 56 57 // Envia resposta 58 strcpy(str ,"Mensagem OK!"); 59 sendto(sck_client ,str ,MSG_SIZE ,0, 60 (sockaddr *) &addr_from ,addr_from_len); 61 62 // Fecha a conexão com o cliente 63 close(sck_client); 64 } 65 66 return 0; 67 } II O cliente faz a comunicação através de um único socket (já que o mesmo estará vinculado ao servidor) Socket com TCP I1 #include <sys/socket.h> 2 #include <arpa/inet.h> 3 #include <unistd.h> 4 #include <iostream > 5 #include <cstring > 6 7 #define MAX_QUEUE 2 8 #define MSG_SIZE 255 9 10 using namespace std; 11 12 int main(int argc , char **argv) { 13 // Construção do socket 14 int sck_server = socket(PF_INET ,SOCK_STREAM ,0); 15 16 // Endereçamento IP (O Servidor aceita conexão de qualquer host) 17 sockaddr_in addr_server; 18 addr_server.sin_family = AF_INET; Socket com TCP 19 addr_server.sin_port = htons (9999); 20 addr_server.sin_addr.s_addr = htonl(INADDR_ANY); 21 22 // Tamanho do endereço 23 socklen_t addr_server_len = sizeof(addr_server); 24 25 // Variáveis do IP remente 26 sockaddr_in addr_from; 27 socklen_t addr_from_len; 28 29 // Faz o bind da porta 30 if(bind(sck_server ,(const sockaddr *) &addr_server ,addr_server_len) 31 == -1) { 32 cout << "Erro no bind" << endl; 33 exit (0); 34 } 35 36 // Define que o bind suporta até 10 conexões na fila Socket com TCP 37 if(listen(sck_server ,MAX_QUEUE) == -1) { 38 cout << "Erro ao ouvir a porta" << endl; 39 exit (0); 40 } 41 42 while (1) { 43 int sck_client = accept(sck_server ,( sockaddr *)&addr_from ,& addr_from_len); 44 char str[MSG_SIZE ]; 45 46 if(sck_client < 0) { 47 cout << "Erro ao aceitar conexão do cliente" << endl; 48 exit (0); 49 } 50 51 // Espera mensagem do cliente 52 bzero(str ,MSG_SIZE); 53 recvfrom(sck_client ,str ,MSG_SIZE ,0, 54 (sockaddr *)&addr_from ,& addr_from_len); Socket com TCP 55 cout << "Mensagem recebida: " << str << endl; 56 57 // Envia resposta 58 strcpy(str ,"Mensagem OK!"); 59 sendto(sck_client ,str ,MSG_SIZE ,0, 60 (sockaddr *) &addr_from ,addr_from_len); 61 62 // Fecha a conexão com o cliente 63 close(sck_client); 64 } 65 66 return 0; 67 } Socket com TCP I No protocolo tcp ao tentar enviar ou receber uma mensagem do cliente o mesmo retornar -1 indica que a conexão com ele caiu. Programação distribuída + Paralela I Todos os exemplos aqui apresentados são sequenciais I Para um sistema UDP ainda é factível mantê-lo em um única thread I Não existe compromisso com a conexão I O protocolo TCP cria um socket com cliente I Em sumo, podemos dizer que “cada socket” ficará numa thread para que a mesma cuide da comunicação com ela
Compartilhar