Capítulo 2 Camada de aplicação - UFFlsousa/redes_i/cap-2.pdf · • O HTTP — Protocolo de...

Preview:

Citation preview

1

Capítulo 2

Camada de aplicação

2

Redes de computadores I

Prof.: Leandro Soares de Sousa

E-mail: lsousa@id.uff.br

Site: http://www.ic.uff.br/~lsousa

Não deixem a matéria acumular!!!

Datas das avaliações, exercícios propostos, transparências,... no site!

3

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

4

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

5

• O ponto central do desenvolvimento de aplicação de rede é escrever programas que rodem em sistemas finais diferentes e se comuniquem entre si.

• Ao desenvolver sua nova aplicação, você precisará escrever um software que rode em vários sistemas finais.

Princípios de aplicações de rede

6

• Esse software poderia ser criado, por exemplo, em C, Java ou Python.

• Você não precisará escrever programas que executem nos elementos do núcleo de rede, como nos roteadores.

Princípios de aplicações de rede

7

• A arquitetura de rede é fixa e provê um conjunto específico de serviços.

• A arquitetura da aplicação é projetada pelo programador e determina como a aplicação é organizada nos vários sistemas finais.

Arquiteturas de aplicação de rede

8

• Em uma arquitetura cliente-servidor há um hospedeiro sempre em funcionamento, denominado servidor, que atende a requisições de muitos outros hospedeiros, denominados clientes.

• Ex.: web, e-mail, ftp, telnet, ssh, scp, …

Arquiteturas de aplicação de rede

9

• A comunicação de uma aplicação de rede ocorre entre “sistemas finais” (hospedeiros) na camada de aplicação.

Arquiteturas de aplicação de rede

10

• A arquitetura P2P utiliza a comunicação direta entre duplas de hospedeiros conectados alternadamente, denominados pares.

• Uma das características mais fortes da arquitetura P2P é sua autoescalabilidade.

• Compartilhamento de arquivos (BitTorrent), telefonia pela Internet (Skype), IPTV (KanKan, Ppstream, ...)

Arquiteturas de aplicação de rede

11

• As futuras aplicações P2P estão diante de três principais desafios:

1. ISP Amigável: atual banda assimétrica, mas com P2P pode colocar pressão nos ISPs

2. Segurança: proteção complicada!

3. Incentivos: usuários participativos

Arquiteturas de aplicação de rede

12Arquiteturas de aplicação de rede

13

• Processos de aplicação, sockets e protocolo de transporte subjacente.

Comunicação entre processos

14

• Uma aplicação de rede consiste em pares de processos que enviam mensagens uns para os outros por meio de uma rede.

• Um processo envia mensagens para a rede e recebe mensagens dela através de uma interface de software denominada socket.

• Para identificar o processo receptor, duas informações devem ser especificadas:

1. o endereço do hospedeiro e 2. um identificador que especifica o processo receptor no

hospedeiro de destino.

Comunicação entre processos

15

• Transferência confiável de dados: a aplicação tolera perdas?

• Vazão: restrição de banda na aplicação?

• Temporização: o tempo fim-a-fim é relevante?

• Segurança: o transporte tem restrição de segurança? (cap.8)

Serviços de transporte disponíveis para aplicações

16

● Serviço TCP:

● orientado a conexão: inicialização requerida entre cliente e servidor / transporte confiável entre processos remetente e receptor

● controle de fluxo: remetente não vai “afogar” receptor● controle de congestionamento: estrangular remetente quando a rede estiver

carregada● não provê: garantias temporais ou de banda mínima

● Serviço UDP:

● transferência de dados não confiável entre processos remetente e receptor● não provê: estabelecimento da conexão, confiabilidade, controle de fluxo,

controle de congestionamento, garantias temporais ou de banda mínima

Pergunta: Qual é o interesse em ter um UDP?

Serviços de transporte disponíveis para aplicações

17

• A Internet disponibiliza dois protocolos de transporte para aplicações, o UDP e o TCP.

• Requisitos de aplicações de rede selecionadas:

Serviços de transporte providos pela Internet

18

• Aplicações populares da Internet, seus protocolos de camada de aplicação e seus protocolos de transporte subjacentes:

Serviços de transporte providos pela Internet

19

Um protocolo de camada de aplicação define:

• Os tipos de mensagens trocadas.

• A sintaxe dos vários tipos de mensagens, tais como os campos da mensagem e como os campos são delineados.

• A semântica dos campos, isto é, o significado da informação nos campos.

• Regras para determinar quando e como um processo envia mensagens e responde a mensagens.

Protocolos de camada de aplicação

20

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

21

• Talvez o que mais atraia a maioria dos usuários da Web é que ela funciona por demanda.

• O HTTP — Protocolo de Transferência de Hipertexto (HyperText Transfer Protocol) —, o protocolo da camada de aplicação da Web, está no coração da Web e é definido no [RFC 1945] e no [RFC 2616].

• O HTTP é executado em dois programas:

1. um cliente e 2. outro servidor.

A Web e o HTTP

22

• Uma página Web é constituída de objetos.

• Um objeto é apenas um arquivo que se pode acessar com um único URL. (ex.: www.ic.uff.br/~lsousa/index.html - hospedeiro - caminho)

• A maioria das páginas Web é constituída de um arquivo-base HTML e diversos objetos referenciados.

• O HTTP usa o TCP como seu protocolo de transporte subjacente (porta 80).

• O HTTP é denominado um protocolo sem estado (stateless – vários protocolos são assim).

A Web e o HTTP

23

• Mecânica do processo:

A Web e o HTTP

24

• Quando a interação cliente-servidor acontece por meio de conexão TCP, o programador da aplicação precisa tomar uma importante decisão:

• Conexões não persistentes (http 1.0) — cada par de requisição/resposta deve ser enviado por uma conexão TCP distinta.

• Conexões persistentes (http 1.1) — todas as requisições e suas respostas devem ser enviadas por uma mesma conexão TCP.

Conexões persistentes e não persistentes

25Conexões persistentes e não persistentes

26

• Quando a interação cliente-servidor acontece por meio de conexão TCP, o programador da aplicação precisa tomar uma importante decisão:

• Conexões não persistentes (http 1.0) — cada par de requisição/resposta deve ser enviado por uma conexão TCP distinta.

• Conexões persistentes (http 1.1) — todas as requisições e suas respostas devem ser enviadas por uma mesma conexão TCP (com ou sem paralelismo – configuração no navegador).

Conexões persistentes e não persistentes

27

Mensagem de requisição HTTP

• Apresentamos a seguir uma mensagem de requisição HTTP típica:

GET /somedir/page.html HTTP/1.1Host: www.someschool.eduConnection: closeUser-agent: Mozilla/5.0Accept-language: fr

Formato da mensagem HTTP

28

• Formato geral de uma mensagem de requisição HTTP

Formato da mensagem HTTP

29

Mensagem de resposta HTTP

• Apresentamos a seguir uma mensagem de resposta HTTP típica:

HTTP/1.1 200 OKConnection: closeDate: Tue, 09 Aug 2011 15:44:04 GMTServer: Apache/2.2.3 (CentOS)Last-Modified: Tue, 09 Aug 2011 15:11:03 GMTContent-Length: 6821Content-Type: text/html(dados dados dados dados dados ...)

Formato da mensagem HTTP

30

• Formato geral de uma mensagem de resposta HTTP

Formato da mensagem HTTP

31

• Na primeira linha da mensagem de resposta servidor → cliente. Alguns códigos típicos:

● 200 OK● sucesso, objeto pedido segue mais adiante nesta mensagem

● 301 Moved Permanently● objeto pedido mudou de lugar, nova localização especificado mais adiante

nesta mensagem (Location:)

● 400 Bad Request● mensagem de pedido não entendida pelo servidor

● 404 Not Found● documento pedido não se encontra neste servidor

● 505 HTTP Version Not Supported● versão de http do pedido não usada por este servidor

Formato da mensagem HTTP

32

Cookies, definidos no [RFC 6265], permitem que sites monitorem seus usuários (privacidade?).

A tecnologia dos cookies tem quatro componentes:

1. uma linha de cabeçalho de cookie na mensagem de resposta HTTP;

2. uma linha de cabeçalho de cookie na mensagem de requisição HTTP;

3. um arquivo de cookie mantido no sistema final do usuário e gerenciado pelo navegador do usuário;

4. um banco de dados de apoio no site.

Interação usuário-servidor: cookies

33

• Mantendo o estado do usuário com cookies.

Interação usuário-servidor: cookies

34

• Um cache Web — também denominado servidor proxy — é uma entidade da rede que atende requisições HTTP em nome de um servidor Web de origem.

Clientes requisitandoobjetos por meio de um cache Web:

Caches Web

35

● GET condicional – mecanismo que permite que um cache verifique se seus objetos estão atualizados.

● Meta: não enviar objeto se cliente já tem (no cache) versão atual

● cache: especifica data da cópia no cache no pedido http

If-modified-since: <date>● servidor: resposta não

contém objeto se cópia no cache é atual:

HTTP/1.0 304 Not Modified

GET condicional

36

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

37

• Em uma sessão FTP típica, o usuário quer transferir arquivos de ou para um hospedeiro remoto.

• HTTP e FTP são protocolos de transferência de arquivos e têm muitas características em comum.

• ftp: RFC 959

• servidor ftp: porta 21

Transferência de arquivo: FTP

38

• FTP transporta arquivos entre sistemas de arquivo local e remoto:

Transferência de arquivo: FTP

39

• Conexões de controle e de dados, protocolo dito “fora de banda” (texto aberto na conexão de controle):

Transferência de arquivo: FTP

40

Alguns dos comandos mais comuns são descritos a seguir:

• USER username: usado para enviar identificação do usuário ao servidor.

• PASS password: usado para enviar a senha do usuário ao servidor.

• LIST: usado para pedir ao servidor que envie uma lista com todos os arquivos existentes no atual diretório remoto.

• RETR filename: usado para extrair um arquivo do diretório atual do hospedeiro remoto.

Camadas e respostas FTP

41

• STOR filename: usado para armazenar um arquivo no diretório atual do hospedeiro remoto.

Algumas respostas típicas, junto com suas possíveis mensagens, são as seguintes:

• 331 Nome de usuário OK, senha requisitada

• 125 Conexão de dados já aberta; iniciando transferência

• 425 Não é possível abrir a conexão de dados

• 452 Erro ao escrever o arquivo

Camadas e respostas FTP

42

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

43

• Uma visão do sistema de e-mail da Internet.

• Três grandes componentes:

● agentes de usuário (UA)

● servidores de correio

● simple mail transfer protocol: SMTP

Correio eletrônico na Internet

44

• Servidores de correio

● caixa de correio contém mensagens de chegada (ainda não lidas) p/ usuário

● fila de mensagens contém mensagens de saída (a serem enviadas)

● protocolo SMTP entre servidores de correio para transferir mensagens de correio

● cliente: servidor de correio que envia

● servidor: servidor de correio que recebe

Correio eletrônico na Internet

45

• Usa TCP para a transferência confiável de msgs do correio do cliente ao servidor, porta 25

● transferência direta: servidor remetente ao servidor receptor

● três fases da transferência

● handshaking (cumprimento)● transferência das mensagens● encerramento

● interação comando/resposta

● comandos: texto ASCII● resposta: código e frase de status

● mensagens precisam ser em ASCII de 7-bits

SMTP (RFC 2821)

46

S: 220 doces.br C: HELO consumidor.br S: 250 Hello consumidor.br, pleased to meet you C: MAIL FROM: <ana@consumidor.br> S: 250 ana@consumidor.br... Sender ok C: RCPT TO: <bernardo@doces.br> S: 250 bernardo@doces.br ... Recipient ok C: DATA S: 354 Enter mail, end with "." on a line by itself C: Voce gosta de chocolate? C: Que tal sorvete? C: . S: 250 Message accepted for delivery C: QUIT S: 221 doces.br closing connection

Interação SMTP típica

47

• O SMTP transfere mensagens de servidores de correio remetentes para servidores de correio destinatários.

• O SMTP é um protocolo “push” (empurre) e o HTTP “pull” (puxe)

Alice envia uma mensagem a Bob:

SMTP

48

• Um cabeçalho de mensagem típico é semelhante a:

From: alice@crepes.frTo: bob@hamburger.eduSubject: Searching for the meaning of life.

• Após o cabeçalho da mensagem, vem uma linha em branco e, em seguida, o corpo da mensagem (em ASCII com 7 bits).

• Se é ASCII de 7 bits, como envio as fotos, vídeos, …? (MIME)

Formatos de mensagem de correio

49

● MIME: multimedia mail extension, RFC 2045, 2056● linhas adicionais no cabeçalho da msg declaram tipo do

conteúdo MIME

Formatos de mensagem de correio: extensões multimídia

50

Text● subtipos exemplos: plain, html● charset=“iso-8859-1”, ascii

Image● subtipos exemplos : jpeg, gif

Video● subtipos exemplos : mpeg, quicktime

Áudio● subtipos exemplos : basic (8-bit codificado mu-law), 32kadpcm (codificação 32

kbps)

Application● outros dados que precisam ser processados por um leitor para serem “visualizados”● subtipos exemplos : msword, octet-stream

Formatos de mensagem de correio: extensões multimídia

51

Tipo Multipart:

From: alice@crepes.fr To: bob@hamburger.edu Subject: Picture of yummy crepe. MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=98766789 --98766789Content-Transfer-Encoding: quoted-printableContent-Type: text/plain

Dear Bob, Please find a picture of a crepe.--98766789Content-Transfer-Encoding: base64Content-Type: image/jpeg

base64 encoded data ..... ......................... ......base64 encoded data --98766789--

Formatos de mensagem de correio: extensões multimídia

52

• SMTP: entrega/armazenamento no servidor do receptor● protocolo de acesso ao correio: recupera do servidor

• POP: Post Office Protocol [RFC 1939]● autorização (agente <-->servidor) e transferência

• IMAP: Internet Mail Access Protocol [RFC 1730]● mais comandos (mais complexo)● manuseio de msgs armazenadas no servidor● HTTP: Hotmail , Yahoo! Mail, Webmail, etc.

Protocolos de acesso ao correio

53

POP3fase de autorização

comandos do cliente: user: declara nomepass: senha

servidor responde+OK-ERR

fase de transação, cliente:list: lista números das msgsretr: recupera msg por númerodele: apaga msgquit:

Protocolos de acesso ao correioS: +OK POP3 server ready C: user ana S: +OK C: pass faminta S: +OK user successfully logged on

C: list S: 1 498 S: 2 912 S: . C: retr 1 S: <message 1 contents> S: . C: dele 1 C: retr 2 S: <message 1 contents> S: . C: dele 2 C: quit S: +OK POP3 server signing off

54

Mais sobre o POP3

● O exemplo anterior usa o modo “download e delete”.● Bob não pode reler as mensagens se mudar de cliente● “Download-e-mantenha”: copia as mensagens em clientes diferentes ● POP3 não mantém estado entre conexões

IMAP

● Mantém todas as mensagens num único lugar: o servidor● Permite ao usuário organizar as mensagens em pastas● O IMAP mantém o estado do usuário entre sessões:

● nomes das pastas e mapeamentos entre as IDs das mensagens e o nome da pasta

Protocolos de acesso ao correio

55

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

56

• Pessoas: muitos identificadores:

● CPF, nome, no. da Identidade

● hospedeiros, roteadores Internet:

● endereço IP (32 bit) - usado p/ endereçar datagramas

● “nome”, ex., jambo.ic.uff.br - usado por gente

● Pergunta: como mapear entre nome e endereço IP?

DNS: o serviço de diretório da Internet

57

• Domain Name System:

● base de dados distribuída implementada na hierarquia de muitos servidores de nomes

• O DNS é (1) um banco de dados distribuído executado em uma hierarquia de servidores de DNS, e (2) um protocolo de camada de aplicação que permite que hospedeiros consultem o banco de dados distribuído.

● nota: função imprescindível da Internet implementada como protocolo de camada de aplicação

● complexidade na borda da rede● Roda sobre UDP e usa a porta 53

● RFCs 1034, 1035● Atualizado em outras RFCs

DNS: o serviço de diretório da Internet

58

O DNS provê alguns outros serviços importantes além da tradução de nomes de hospedeiro para endereços IP:

• Apelidos (aliasing) de hospedeiro.

• Apelidos de servidor de correio.

• Distribuição de carga.

DNS: o serviço de diretório da Internet

59

• Nenhum servidor DNS isolado tem todos os mapeamentos para todos os hospedeiros da Internet.

• Em vez disso, os mapeamentos são distribuídos pelos servidores DNS.

Parte da hierarquia de servidores DNS

DNS: o serviço de diretório da Internet

60

• Por que não centralizar o DNS?

● ponto único de falha● volume de tráfego● base de dados centralizada e distante● manutenção (da BD)

DNS: o serviço de diretório da Internet

61

• Servidores DNS raiz em 2012 (nome, organização, localização)

DNS: o serviço de diretório da Internet

62

• Servidores DNS locais:

● Não pertence necessariamente à hierarquia

● Cada ISP (ISP residencial, companhia, universidade) possui um.

● Também chamada do “servidor de nomes default”

● Quando um hospedeiro faz uma consulta DNS, a mesma é enviada para o seu servidor DNS local

● Atua como um intermediário, enviando consultas para a hierarquia.

DNS: o serviço de diretório da Internet

63

• Interação dos diversos servidores DNS:

● consulta recursiva:● transfere a

responsabilidade de resolução do nome para o servidor de nomes contatado

● carga pesada?● consulta interativa:

● servidor consultado responde com o nome de um servidor de contato

● “Não conheço este nome, mas pergunte para esse servidor”

DNS: o serviço de diretório da Internet

64

• O DNS explora extensivamente o cache para melhorar o desempenho quanto ao atraso e reduzir o número de mensagens DNS que dispara pela Internet.

• Consultas recursivas em DNS

DNS: o serviço de diretório da Internet

65

• Um RR (registro de recurso) é uma tupla de quatro elementos que contém os seguintes campos:

(Nome, Valor, Tipo, Sobrevida)

● Tipo=A ● nome é nome de hospedeiro● valor é o seu endereço IP

● Tipo=NS● nome é domínio (p.ex. foo.com.br)● valor é endereço IP de servidor oficial de nomes para este domínio

● Tipo=CNAME● nome é nome alternativo (alias) para algum nome “canônico” (verdadeiro)● valor é o nome canônico

● Tipo=MX● nome é domínio ● valor é nome do servidor de correio para este domínio

Registros e mensagens DNS

66

• DNS: mensagens de pedido e resposta, ambas com o mesmo formato de mensagem

Registros e mensagens DNS

cabeçalho de msg:

● identificação: ID de 16 bit para pedido e resposta ao pedido usam mesmo ID

● flags:● pedido ou resposta● recursão desejada● recursão permitida● resposta é oficial

67

● Inserindo registros no DNS

● Exemplo: acabou de cria a empresa “Network Utopia”

● Registra o nome netutopia.com.br em uma entidade registradora (e.x., Registro.br)

● Tem de prover para a registradora os nomes e endereços IP dos servidores DNS oficiais (primário e secundário)

● Registradora insere dois RRs no servidor TLD .br:

(netutopia.com.br, dns1.netutopia.com.br, NS)(dns1.netutopia.com.br, 212.212.212.1, A)

● Põe no servidor oficial um registro do tipo A para www.netutopia.com.br e um registro do tipo MX para netutopia.com.br

● Como as pessoas vão obter o endereço IP do seu site?

Registros e mensagens DNS

68

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

69

Distribuição de arquivos P2P

• Na distribuição de arquivos P2P, cada par pode redistribuir qualquer parte do arquivo recebido para outros pares, auxiliando, assim, o servidor no processo de distribuição.

• O tempo de distribuição é o tempo necessário para que todos os N pares obtenham uma cópia do arquivo.

• O BitTorrent é um protocolo P2P popular para distribuição de arquivos.

Aplicações P2P

70

Distribuição de arquivos P2P

Um problema ilustrativo de distribuição de arquivo

Aplicações P2P

71

Distribuição de arquivos P2P

Tempo de distribuição para arquiteturas P2P e cliente-servidor

Aplicações P2P

72

Distribuição de arquivos P2P

Distribuição de arquivos com o BitTorrent

Aplicações P2P

73

Distributed Hash Tables (DHTs)

• Vamos considerar como montar uma versão distribuída, P2P, de um banco de dados, que guardará os pares (chave, valor) por milhões.

• No sistema P2P, cada par só manterá um pequeno subconjunto da totalidade (chave, valor).

• Permitiremos que qualquer par consulte o banco de dados distribuído com uma chave em particular.

Aplicações P2P

74

Distributed Hash Tables (DHTs)

• O banco de dados distribuído, então, localizará os pares que possuem os pares (chave, valor) correspondentes e retornará os pares chave valor ao consultante.‑

• Qualquer par também poderá inserir novos pares chave-valor no banco de dados.

• Esse banco de dados distribuído é considerado como uma tabela hash distribuída (DHT — Distributed Hash Table).

• Problema: cada nó deve conter apontamentos para todos os outros nós?

Aplicações P2P

75

Distributed Hash Tables (DHTs)

• O DHT circular oferece uma solução bastante elegante para reduzir a quantidade de informação sobreposta que cada par deve gerenciar.

Aplicações P2P

76

Distributed Hash Tables (DHTs)

• Em sistemas P2P, um par pode vir ou ir sem aviso.

• Suponha que o par 5 da figura anterior saia de modo abrupto.

• Os dois pares precedentes ao que saiu (4 e 3) saberão que o par saiu, pois não responde mais às mensagens de ping.

• Os pares 4 e 3 precisam, portanto, atualizar as informações do estado de seu sucessor.

Aplicações P2P

77

Distributed Hash Tables (DHTs)

• Consideraremos agora como o par 4 atualiza seu estado:

1. O par 4 substitui seu primeiro sucessor (par 5) por seu segundo sucessor (par 8).

2. O par 4, então, pergunta a seu novo primeiro sucessor (par 8) o identificador e o endereço IP de seu sucessor imediato (par 10). O par 4, então, torna o par 10 seu segundo sucessor.

Aplicações P2P

78

2.1 – Princípios das aplicações de rede2.2 – A Web e o HTTP2.3 – Transferência de arquivos: FTP2.4 – Correio eletrônico na Internet2.5 – DNS: o serviço de diretório da Internet2.6 – Aplicações P2P2.7 – Programação de Sockets: criando aplicações de rede

Sumário

79

• Há dois tipos de aplicações de rede.

• Um deles é uma execução cuja operação é especificada em um padrão de protocolo.

• O outro tipo de aplicação de rede é uma aplicação de rede proprietária.

Programação de sockets

• Usaremos a aplicação cliente-servidor simples a seguir para demonstrar a programação de socket para UDP e TCP:

Programação de sockets: criando aplicações de rede

80

1. Um cliente lê uma linha de caracteres (dados) do teclado e a envia para o servidor.

2. O servidor recebe os dados e converte os caracteres para maiúsculas.

3. O servidor envia os dados modificados ao cliente.

4. O cliente recebe os dados modificados e apresenta a linha em sua tela.

Programação de sockets com UDP

81

A aplicação cliente-servidor usando UDP

Programação de sockets com UDP

82

• O processo TCPServer tem dois sockets

Programação de sockets com TCP

83

• A aplicação cliente-servidor usando TCP

Programação de sockets com TCP

84

• No livro texto podem ser encontrados os fontes em Python dos programas.

• No site do curso estão disponíveis as versões em: Java, Python e C.

• Aqui vou apresentar em C

Programação de sockets

85

● Cliente/Servidor de repetição (echo client/server)

● O cliente envia uma mensagem que é repetida de volta

Programação de sockets

Cliente Servidor

Mensagem

Mensagem

86

● Cliente/Servidor de repetição (echo client/server)

● O cliente envia uma mensagem que é repetida de volta

● Os fontes estão no site, tanto para TCP quanto para UDP!!!

● Vamos executar em sala de aula!!!

Programação de sockets

Cliente (tc.c/uc.c)

Servidor(ts.c/us.c)

Mensagem

Mensagem

87Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

88Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

CABEÇALHO

89Programação de sockets ● Cliente/Servidor UDP (Servidor - cabeçalho)// No codeblocks (Windows) inclua no menu em: Project ->// Build Options...-> Linker settings -> Other link options: // -l wsock32// Se for no Linux comente essa linha e compile no terminal: // gcc -o us us.c#define WIN #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifdef WIN#include <winsock2.h>#else#include <sys/socket.h>#include <arpa/inet.h>#endif

#define TAM_MENSAGEM 255 /* mensagem de maior tamanho */

#define PORTA_SERVIDOR_UDP 8888

90Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

MAIN()

91Programação de sockets ● Cliente/Servidor UDP (Servidor – main - variáveis)int main(){ /* Socket */ int sock; /* Resultado das funções */ int resultado; /* Endereço do Cliente */ struct sockaddr_in endereco; /* Buffer para a recepção da string de echo */ char mensagem[TAM_MENSAGEM]; #ifdef WIN /* Início do ambiente Windows */ WORD wPackedValues; WSADATA SocketInfo; int nLastError,

nVersionMinor = 1, nVersionMajor = 1;

wPackedValues = (WORD)(((WORD)nVersionMinor)<< 8)| (WORD)nVersionMajor; nLastError = WSAStartup(wPackedValues, &SocketInfo);#endif

92Programação de sockets ● Cliente/Servidor UDP (Servidor – main - variáveis)sock = criar_socket(PORTA_SERVIDOR_UDP);if (sock < 0){printf("\nErro na criação do socket!\n");return(1);}

for (;;) /* Loop eterno */{ /* Recebe mensagem do cliente */ resultado = receber_mensagem(mensagem,sock,&endereco); if (resultado < 0) {printf("\nErro no recebimento da mensagem\n");return(1);}

/* Devolve a mensagem para o cliente */ resultado = enviar_mensagem(mensagem,sock,&endereco); if (resultado < 0) {printf("\nErro no envio da mensagem\n");return(1);}} /* não passa por aqui */}

93Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

94Programação de sockets ● Cliente/Servidor UDP (Servidor – criar_socket)int criar_socket(int porta){ int sock; /* Socket para retornar */ struct sockaddr_in endereco; /* Endereço Local */ /* Criação do socket datagrama/UDP para recepção e envio de pacotes */ if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {printf("\nErro na criação do socket!\n");fflush(stdout);return(-1);} /* Se precisar de uma porta específica */ if (porta > 0) { /* Construção da estrutura de endereço local */ /* Zerar a estrutura */ memset(&endereco, 0, sizeof(endereco)); /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Qualquer interface de entrada */ endereco.sin_addr.s_addr = htonl(INADDR_ANY); /* Porta local */ endereco.sin_port = htons(porta); /* Instanciar o endereco local */ if (bind(sock, (struct sockaddr *) &endereco, sizeof(endereco)) < 0) {printf("\nErro no bind()!\n");fflush(stdout);return(-1);} } return(sock);} // socket(int socket_family, int socket_type, int protocol);

95Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

96Programação de sockets ● Cliente/Servidor UDP (Servidor – receber_mensagem)

int receber_mensagem(char *mensagem,int sock, struct sockaddr_in *endereco){ /* Define o tamanho do endereço de recepção e envio */ int tamanho_endereco = sizeof(struct sockaddr_in); /* Limpar o buffer da mensagem */ memset((void *) mensagem,(int) NULL,TAM_MENSAGEM); /* Espera pela recepção de alguma mensagem de algum cliente */ if (recvfrom(sock, mensagem, TAM_MENSAGEM - 1, 0, (struct sockaddr *) endereco, &tamanho_endereco) < 0) { printf("\nErro na recepção da mensagem\n");fflush(stdout); return(-1); } printf("\nUDP Servidor: Recebi (%s)\n",mensagem);fflush(stdout); return(0);}// ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

97Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

98Programação de sockets ● Cliente/Servidor UDP (Servidor – receber_mensagem)int enviar_mensagem(char *mensagem,int sock, struct sockaddr_in *endereco){ /* Devolve o conteúdo do datagrama para o cliente */ if (sendto(sock, mensagem, strlen(mensagem), 0, (struct sockaddr *) endereco, sizeof(struct sockaddr)) != strlen(mensagem)) { printf("\nErro no envio da mensagem\n"); return(-1); }

printf("\nUDP Servidor: Enviei (%s)\n",mensagem);

return(0);}//ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

99Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

CABEÇALHO

100Programação de sockets ● Cliente/Servidor UDP (Cliente - cabeçalho)// No codeblocks (Windows) inclua no menu em: Project ->// Build Options...-> Linker settings -> Other link options: // -l wsock32// Se for no Linux comente essa linha e compile no terminal: // gcc -o uc uc.c#define WIN #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifdef WIN#include <winsock2.h>#else#include <sys/socket.h>#include <arpa/inet.h>#endif

#define TAM_MENSAGEM 255 /* mensagem de maior tamanho */

#define PORTA_SERVIDOR_UDP 8888

101Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

MAIN()

102Programação de sockets ● Cliente/Servidor UDP (Cliente – main - variáveis)int main(int argc, char **argv){ /* Socket */ int sock; /* Resultado das funções */ int resultado; /* IP do servidor */ char IP[TAM_MENSAGEM]; /* Buffer para a recepção da string de echo */ char mensagem[TAM_MENSAGEM]; #ifdef WIN /* Início do ambiente Windows */ WORD wPackedValues; WSADATA SocketInfo; int nLastError,

nVersionMinor = 1, nVersionMajor = 1;

wPackedValues = (WORD)(((WORD)nVersionMinor)<< 8)| (WORD)nVersionMajor; nLastError = WSAStartup(wPackedValues, &SocketInfo);#endif

103Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

MAIN()

104Programação de sockets ● Cliente/Servidor UDP (Cliente – main - Parâmetros)

/* Parâmetros - INICIO */

/* Testa se o número de parâmetros está correto */if (argc != 3) { printf("Uso: %s <IP Servidor> <Palavra de Echo>\n", argv[0]); Return(1); /* exemplo: uc 127.0.0.1 oi */ /* exemplo: uc 127.0.0.1 “oi estou aqui” */}

memset((void *) IP ,(int) NULL,TAM_MENSAGEM);strcpy(IP ,argv[1]); /* IP Servidor (local 127.0.0.1) */

memset((void *) mensagem,(int) NULL,TAM_MENSAGEM);strcpy(mensagem,argv[2]); /* Mensagem */

/* Parâmetros - FINAL */

105Programação de sockets ● Cliente/Servidor UDP (Cliente – main -cont.)

sock = criar_socket(0); if (sock < 0) {printf("\nErro na criação do socket!\n");return(1);} /* Envia mensagem para o servidor */ resultado = enviar_mensagem(mensagem,sock,IP); if (resultado < 0) {printf("\nErro no envio da mensagem\n");return(1);} /* Recebe mensagem do servidor */ resultado = receber_mensagem(sock); if (resultado < 0) {printf("\nErro no recebimento da mensagem\n");return(1);} /* Fecha o socket e retorna */ close(sock); return(0);}

106Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

107Programação de sockets ● Cliente/Servidor UDP (Cliente – criar_socket)

int criar_socket(int porta){ int sock; /* Socket para retornar */ struct sockaddr_in endereco; /* Endereço Local */ /* Criação do socket datagrama/UDP para recepção e envio de pacotes */ if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {printf("\nErro na criação do socket!\n");fflush(stdout);return(-1);} /* Se precisar de uma porta específica */ if (porta > 0) { /* Construção da estrutura de endereço local */ /* Zerar a estrutura */ memset(&endereco, 0, sizeof(endereco)); /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Qualquer interface de entrada */ endereco.sin_addr.s_addr = htonl(INADDR_ANY); endereco.sin_port = htons(porta); /* Porta local */ /* Instanciar o endereco local */ if (bind(sock, (struct sockaddr *) &endereco, sizeof(endereco)) < 0) {printf("\nErro no bind()!\n");fflush(stdout);return(-1);} } return(sock);}

108Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

109Programação de sockets ● Cliente/Servidor UDP (Cliente – enviar_mensagem)int enviar_mensagem(char *mensagem,int sock,char *IP){ struct sockaddr_in endereco; /* Endereço do Servidor */ /* Construção da estrutura de endereço do servidor */ /* Zerar a estrutura */ memset(&endereco, 0, sizeof(endereco)); /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Endereço IP do Servidor */ endereco.sin_addr.s_addr = inet_addr(IP); /* Porta do Servidor */ endereco.sin_port = htons(PORTA_SERVIDOR_UDP); /* Enviar mensagem para o servidor */ if (sendto(sock, mensagem, strlen(mensagem), 0, (struct sockaddr *) &endereco, sizeof(struct sockaddr_in)) != strlen(mensagem)) {printf("\nErro no envio da mensagem\n");return(-1);} printf("\nUDP Cliente: Enviei (%s)\n",mensagem); return(0);}

110Programação de sockets ● Cliente/Servidor UDP

receber_mensagem(socket_servidor, mensagem)

Cliente (UC.C)Servidor (US.C)

socket_servidor = criar_socket(8888)

enviar_mensagem(socket_servidor, IP_cliente,

porta_cliente mensagem)

enviar_mensagem(socket_cliente, IP_servidor, porta_servidor, mensagem)

receber_parâmetros()socket_cliente = criar_socket(0)

receber_mensagem(socket_cliente, mensagem)

fechar_socket, socket_cliente)

mensagem

mensagem

mensagem

Mensagem /IP Servidor

Mensagem /IP Servidor

111Programação de sockets ● Cliente/Servidor UDP (Cliente – receber_mensagem)

int receber_mensagem(int sock){ /* Buffer para a recepção da string de echo */ char mensagem[TAM_MENSAGEM]; struct sockaddr_in endereco; /* Endereço do Servidor */ /* Define o tamanho do endereço de recepção e envio */ int tamanho_endereco = sizeof(struct sockaddr_in); /* Limpar o buffer da mensagem */ memset((void *) mensagem,(int) NULL,TAM_MENSAGEM); /* Espera pela recepção de alguma mensagem de algum cliente */ if (recvfrom(sock, mensagem, TAM_MENSAGEM - 1, 0, (struct sockaddr *) &endereco, &tamanho_endereco) < 0) { printf("\nErro na recepção da mensagem\n");fflush(stdout); return(-1); } printf("\nUDP Cliente: Recebi (%s)\n",mensagem);fflush(stdout); return(0);}

112Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

113Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

114Programação de sockets ● Cliente/Servidor TCP (Servidor - cabeçalho)// No codeblocks (Windows) inclua no menu em: Project ->// Build Options...-> Linker settings -> Other link options: // -l wsock32// Se for no Linux comente essa linha e compile no terminal: // gcc -o ts ts.c#define WIN #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifdef WIN#include <winsock2.h>#else#include <sys/socket.h>#include <arpa/inet.h>#endif#define TAM_MENSAGEM 255 /* mensagem de maior tamanho *//* Número máximo de requisições para conexão pendentes */#define MAXPENDING 5 #define PORTA_SERVIDOR_TCP 9999

115Programação de sockets ● Cliente/Servidor TCP (Servidor – main - variáveis)

int main(){ /* Socket */ int sock; /* Socket da conexão com o cliente */ int socket_cliente; /* Resultado das funções */ int resultado; /* Buffer para a recepção da string de echo */ char mensagem[TAM_MENSAGEM]; #ifdef WIN /* Início do ambiente Windows */ WORD wPackedValues; WSADATA SocketInfo; int nLastError,

nVersionMinor = 1, nVersionMajor = 1;

wPackedValues = (WORD)(((WORD)nVersionMinor)<< 8)| (WORD)nVersionMajor; nLastError = WSAStartup(wPackedValues, &SocketInfo);#endif

116Programação de sockets ● Cliente/Servidor TCP (Servidor – main – cont.)

sock = criar_socket(PORTA_SERVIDOR_TCP);if (sock < 0){printf("\nErro na criação do socket!\n");return(1);}for (;;) /* Loop eterno */{ /* Aguarda por uma conexão e a aceita criando o socket de contato com o cliente */ socket_cliente = aceitar_conexao(sock); if (socket_cliente == 0) {printf("\nErro na conexao do socket!\n");return(1);} /* Recebe a mensagem do cliente */ resultado = receber_mensagem(mensagem,socket_cliente); if (resultado < 0) {printf("\nErro no recebimento da mensagem\n");return(1);} /* Devolve o conteúdo da mensagem para o cliente */ resultado = enviar_mensagem(mensagem,socket_cliente); if (resultado < 0) {printf("\nErro no envio da mensagem\n");return(1);} close(socket_cliente); /* Fecha o socket do cliente */}/* não passa por aqui */}

117Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

118Programação de sockets ● Cliente/Servidor TCP (Servidor – criar_socket)

int criar_socket(int porta){ int sock; struct sockaddr_in endereco; /* Endereço Local */ /* Criação do socket TCP para recepção e envio de pacotes */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {printf("\nErro na criação do socket!\n");return(-1);} if (porta > 0) { /* Construção da estrutura de endereço local */ memset(&endereco, 0, sizeof(endereco)); /* Zerar a estrutura */ /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Qualquer interface de entrada */ endereco.sin_addr.s_addr = htonl(INADDR_ANY); endereco.sin_port = htons(porta); /* Porta local */ /* Instanciar o endereco local */ if (bind(sock, (struct sockaddr *) &endereco, sizeof(endereco)) < 0) {printf("\nErro no bind()!\n");return(-1);} /* Indica que o socket escutara as conexões */

if (listen(sock, MAXPENDING) < 0) {printf("\nErro no listen()!\n");return(-1);} } return(sock);}

119Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

120Programação de sockets ● Cliente/Servidor TCP (Servidor – aceitar_conexao)

int aceitar_conexao(int sock){ int socket_cliente; struct sockaddr_in endereco; /* Endereço Local */ int tamanho_endereco;

/* Define o tamanho do endereço de recepção e envio */ tamanho_endereco = sizeof(endereco);

/* Aguarda pela conexão de um cliente */ if ((socket_cliente = accept(sock, (struct sockaddr *) &endereco, &tamanho_endereco)) < 0) { printf("\nErro no accept()!\n");fflush(stdout); return(0); } return(socket_cliente);}

121Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

122Programação de sockets ● Cliente/Servidor TCP (Servidor – receber_mensagem)int receber_mensagem(char *mensagem,int sock){ /* Limpar o buffer da mensagem */ memset((void *) mensagem,(int) NULL,TAM_MENSAGEM);

/* Espera pela recepção de alguma mensagem do cliente conectado */ if (recv(sock, mensagem, TAM_MENSAGEM, 0) < 0) { printf("\nErro na recepção da mensagem\n"); return(-1); }

printf("\nTCP Servidor: Recebi (%s)\n",mensagem);

return(0);}// ssize_t recv(int sockfd, void *buf, size_t len, int flags);

123Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

124Programação de sockets ● Cliente/Servidor TCP (Servidor – enviar_mensagem)

int enviar_mensagem(char *mensagem,int sock){ /* Devolve o conteúdo da mensagem para o cliente */ if (send(sock, mensagem, strlen(mensagem), 0) != strlen(mensagem)) { printf("\nErro no envio da mensagem\n"); return(-1); }

printf("\nTCP Servidor: Enviei (%s)\n",mensagem);

return(0);}

// ssize_t send(int sockfd, const void *buf, size_t len, int flags);

125Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

126Programação de sockets ● Cliente/Servidor TCP (Cliente - cabeçalho)

// No codeblocks (Windows) inclua no menu em: Project ->// Build Options...-> Linker settings -> Other link options: // -l wsock32// Se for no Linux comente essa linha e compile no terminal: // gcc -o tc tc.c#define WIN #include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#ifdef WIN#include <winsock2.h>#else#include <sys/socket.h>#include <arpa/inet.h>#endif#define TAM_MENSAGEM 255 /* mensagem de maior tamanho *//* Número máximo de requisições para conexão pendentes */ #define PORTA_SERVIDOR_TCP 9999

127Programação de sockets ● Cliente/Servidor TCP (Cliente – main - variáveis)int main(int argc, char **argv){ /* Socket */ int sock; /* Resultado das funções */ int resultado; /* Buffer para a recepção da string de echo */ char mensagem[TAM_MENSAGEM]; /* Endereço IP do Servidor */ char IP[TAM_MENSAGEM]; #ifdef WIN /* Início do ambiente Windows */ WORD wPackedValues; WSADATA SocketInfo; int nLastError,

nVersionMinor = 1, nVersionMajor = 1;

wPackedValues = (WORD)(((WORD)nVersionMinor)<< 8)| (WORD)nVersionMajor; nLastError = WSAStartup(wPackedValues, &SocketInfo);#endif

128Programação de sockets ● Cliente/Servidor TCP (Cliente – main - parâmetros)

/* Parâmetros - INICIO */ /* Testa se o número de parâmetros está correto */ if (argc != 3) { printf("Uso: %s <IP Servidor> <Palavra de Echo>\n" , argv[0]); return(1);/* exemplo: tc 127.0.0.1 oi */ /* exemplo: tc 127.0.0.1 “oi estou aqui” */ } memset((void *) IP ,(int) NULL,TAM_MENSAGEM); strcpy(IP ,argv[1]); /* IP Servidor */ memset((void *) mensagem,(int) NULL,TAM_MENSAGEM); strcpy(mensagem,argv[2]); /* Parâmetros - FINAL */

129Programação de sockets ● Cliente/Servidor TCP (Cliente – main – cont.) /* Criação do socket */ sock = criar_socket(0); if (sock < 0) {printf("\nErro na criação do socket!\n");return(1);} /* Estabelecer conexão com o servidor */ resultado = conectar_com_servidor(sock,IP,PORTA_SERVIDOR_TCP); if (resultado < 0) {printf("\nErro no recebimento da mensagem\n");return(1);} /* Enviar mensagem para o servidor */ resultado = enviar_mensagem(mensagem,sock); if (resultado < 0) {printf("\nErro no envio da mensagem\n");return(1);} /* Recebendo como resposta a mesma string vinda do servidor */ resultado = receber_mensagem(mensagem,sock); if (resultado < 0) {printf("\nErro no recebimento da mensagem\n");return(1);} /* Fechar socket */ close(sock); return(0);}

130Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

131Programação de sockets ● Cliente/Servidor TCP (Cliente – criar_socket)

int criar_socket(int porta){ int sock; struct sockaddr_in endereco; /* Endereço Local */ /* Criação do socket TCP para recepção e envio de pacotes */ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {printf("\nErro na criação do socket!\n");return(-1);} if (porta > 0) { /* Construção da estrutura de endereço local */ /* Zerar a estrutura */ memset(&endereco, 0, sizeof(endereco)); /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Qualquer interface de entrada */ endereco.sin_addr.s_addr = htonl(INADDR_ANY); endereco.sin_port = htons(porta); /* Porta local */ /* Instanciar o endereco local */ if (bind(sock, (struct sockaddr *) &endereco, sizeof(endereco)) < 0) {printf("\nErro no bind()!\n");return(-1);} /* Indica que o socket escutara as conexões */ if (listen(sock, MAXPENDING) < 0) {printf("\nErro no listen()!\n");return(-1);} } return(sock);}

132Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

133Programação de sockets ● Cliente/Servidor TCP (Cliente - conectar_com_servidor)

int conectar_com_servidor(int sock,char *IP,int porta){ struct sockaddr_in endereco; /* Endereço Local */ /* Construção da estrutura de endereço do servidor */ /* Zerar a estrutura */ memset(&endereco, 0, sizeof(endereco)); /* Família de endereçamento da Internet */ endereco.sin_family = AF_INET; /* Endereço IP do Servidor */ endereco.sin_addr.s_addr = inet_addr(IP); /* Porta do Servidor */ endereco.sin_port = htons(porta); /* Estabelecimento da conexão com o servidor de echo */ if (connect(sock, (struct sockaddr *) &endereco, sizeof(endereco)) < 0) {printf("\nErro no connect()!\n");fflush(stdout);return(-1);} return(0);}

134Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

135Programação de sockets ● Cliente/Servidor TCP (Cliente - enviar_mensagem)

int enviar_mensagem(char *mensagem,int sock){ /* Envia o conteúdo da mensagem para o cliente */ if (send(sock, mensagem, strlen(mensagem), 0) != strlen(mensagem)) { printf("\nErro no envio da mensagem\n"); return(-1); }

printf("\nTCP Cliente: Enviei (%s)\n",mensagem);

return(0);}

136Programação de sockets ● Cliente/Servidor TCP

receber_mensagem(mensagem,socket_cliente)

Cliente (TC.C)Servidor (TS.C)

sock = criar_socket(9999)

enviar_mensagem(mensagem,socket_cliente)

enviar_mensagem(mensagem,sock)

conectar_com_servidor(sock,IP,9999)

receber_mensagem(mensagem,sock)

mensagemmensagem

mensagem

mensagem /IP Servidor

socket_cliente = aceitar_conexao(sock)

mensagem

conexão

Receber parâmetrossock = criar_socket(0)

137Programação de sockets ● Cliente/Servidor TCP (Cliente - receber_mensagem)

int receber_mensagem(char *mensagem,int sock){ /* Limpar o buffer da mensagem */ memset((void *) mensagem,(int) NULL,TAM_MENSAGEM); /* Espera pela recepção de alguma mensagem do cliente conectado*/ if (recv(sock, mensagem, TAM_MENSAGEM, 0) < 0) { printf("\nErro na recepção da mensagem\n"); return(-1); }

printf("\nTCP Cliente: Recebi (%s)\n",mensagem);

return(0);}

138Programação de sockets

● Testem os programas!

● Vejam como eles funcionam!

● Coloquem mensagens de instrumentação no código para acompanhar os passos!

139

Capítulo 2 - FIM

Recommended