1
Capítulo 2
Camada de aplicação
2
Redes de computadores I
Prof.: Leandro Soares de Sousa
E-mail: [email protected]
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
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
4
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
Princípios de aplicações
de rede
• O núcleo 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.
5
Princípios de aplicações
de rede
• 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
roteadores e comutadores.
6
Arquiteturas de aplicação
de rede
• 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.
7
Arquiteturas de aplicação
de rede
• 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, …
8
Arquiteturas de aplicação
de rede
9
• A comunicação de uma
aplicação de rede ocorre
entre sistemas finais na
camada de aplicação.
Arquiteturas de aplicação
de rede
• 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, ...)
10
Arquiteturas de aplicação
de rede
• 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
11
Arquiteturas de aplicação
de rede
12
Comunicação entre
processos
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.
Serviços de transporte
disponíveis para aplicações
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
●
Serviço TCP:
●
●
●
●
●
16
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
providos pela Internet
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:
Protocolos de camada de
aplicação
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.
20
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
21
A Web e o HTTP
• 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.
22
A Web e o HTTP
• 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).
23
A Web e o HTTP
• Mecânica do processo:
Conexões persistentes e
não persistentes
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
25
Conexõ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).
Formato da mensagem
HTTP
27
Mensagem de requisição HTTP
• Apresentamos a seguir uma mensagem de requisição
HTTP típica:
GET /somedir/page.html HTTP/1.1
Host: www.someschool.edu
Connection: close
User-agent: Mozilla/5.0
Accept-language: fr
Formato da mensagem
HTTP
• Formato geral de uma mensagem de requisição HTTP
28
Formato da mensagem
HTTP
29
Mensagem de resposta HTTP
• Apresentamos a seguir uma mensagem de resposta HTTP
típica:
HTTP/1.1 200 OK
Connection: close
Date: Tue, 09 Aug 2011 15:44:04 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 09 Aug 2011 15:11:03 GMT
Content-Length: 6821
Content-Type: text/html
(dados dados dados dados dados ...)
Formato da mensagem
HTTP
• Formato geral de uma mensagem de resposta HTTP
30
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
Interação usuário-servidor:
cookies
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.
34
Caches Web
• 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 requisitando
objetos por meio de
um cache Web:
35
GET condicional
●
●
●
●
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
36
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
37
Transferência de arquivo:
FTP
• 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):
40
Camadas e respostas FTP
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.
41
Camadas e respostas FTP
• STOR filename: usado para armazenar um arquivo no
diretório atual do hospedeiro remoto.
Algumas respostas típicas,
mensagens, são as seguintes:
junto
com
suas
possíveis
• 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
42
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
Correio eletrônico na Internet
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
SMTP (RFC 2821)
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
●
●
●
●
interação comando/resposta
●
●
●
handshaking (cumprimento)
transferência das mensagens
encerramento
comandos: texto ASCII
resposta: código e frase de status
mensagens precisam ser em ASCII de 7-bits
Interação SMTP típica
S: 220 doces.br
C: HELO consumidor.br
S: 250 Hello consumidor.br, pleased to meet you
C: MAIL FROM: <[email protected]>
S: 250 [email protected]... Sender ok
C: RCPT TO: <[email protected]>
S: 250 [email protected] ... 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
46
47
SMTP
• 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:
Formatos de mensagem
de correio
48
• Um cabeçalho de mensagem típico é semelhante a:
From: [email protected]
To: [email protected]
Subject: 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:
extensões multimídia
●
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
Tipo Multipart:
From: [email protected]
To: [email protected]
Subject: Picture of yummy crepe.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=98766789
--98766789
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain
Dear Bob,
Please find a picture of a crepe.
--98766789
Content-Transfer-Encoding: base64
Content-Type: image/jpeg
base64 encoded data .....
.........................
......base64 encoded data
--98766789--
51
Protocolos de acesso ao correio
• 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.
52
Protocolos de acesso ao correio
POP3
fase de autorização
comandos do cliente:
user: declara nome
pass: senha
servidor responde
+OK
-ERR
fase de transação, cliente:
list: lista números das msgs
retr: recupera msg por número
dele: apaga msg
quit:
S:
C:
S:
C:
S:
C:
S:
S:
S:
C:
S:
S:
C:
C:
S:
S:
C:
C:
S:
53
+OK POP3 server ready
user ana
+OK
pass faminta
+OK user successfully logged on
list
1 498
2 912
.
retr 1
<message 1 contents>
.
dele 1
retr 2
<message 1 contents>
.
dele 2
quit
+OK POP3 server signing off
Protocolos de acesso ao correio
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
54
55
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
DNS: o serviço de
diretório da Internet
• 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?
56
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
• 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)
60
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
• 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
64
Registros e mensagens
DNS
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
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
Registros e mensagens
DNS
●
Inserindo registros no DNS
●
Exemplo: acabou de cria a empresa “Network Utopia”
●
67
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?
68
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
69
Aplicações P2P
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.
70
Aplicações P2P
Distribuição de
arquivos P2P
Um problema ilustrativo de
distribuição de arquivo
71
Aplicações P2P
Distribuição de arquivos P2P
Tempo de distribuição
para arquiteturas P2P
e cliente-servidor
72
Aplicações P2P
Distribuição de
arquivos P2P
Distribuição de arquivos
com o BitTorrent
73
Aplicações P2P
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.
74
Aplicações P2P
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 chavevalor
‑
ao consultante.
• Qualquer par também poderá inserir novos pares chavevalor no banco de dados.
• Esse banco de dados distribuído é considerado como uma
tabela hash distribuída (DHT — Distributed Hash Table).
75
Aplicações P2P
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.
76
Aplicações P2P
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.
77
Aplicações P2P
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.
78
Sumário
2.1 – Princípios das aplicações de rede
2.2 – A Web e o HTTP
2.3 – Transferência de arquivos: FTP
2.4 – Correio eletrônico na Internet
2.5 – DNS: o serviço de diretório da Internet
2.6 – Aplicações P2P
2.7 – Programação de Sockets: criando aplicações de rede
Programação de sockets:
criando aplicações de rede
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
com UDP
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
A aplicação
clienteservidor
usando UDP
81
Programação de sockets
com TCP
• O processo TCPServer tem dois sockets
82
Programação de sockets
com TCP
• A aplicação
clienteservidor
usando
TCP
83
Programação de sockets
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
Mensagem
Cliente
Servidor
Mensagem
Programação de sockets
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!!!
Cliente
(tc.c/uc.c)
Mensagem
Mensagem
Servidor
(ts.c/us.c)
Programação de sockets
●
87
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
88
Cliente/Servidor UDP
Servidor (US.C)
CABEÇALHO
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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
89
Programação de sockets
●
90
Cliente/Servidor UDP
Servidor (US.C)
MAIN()
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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
91
Programação de sockets
92
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 */
}
Programação de sockets
●
93
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
94
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);
Programação de sockets
●
95
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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);
96
Programação de sockets
●
97
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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);
98
Programação de sockets
●
99
Cliente/Servidor UDP
Servidor (US.C)
CABEÇALHO
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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
100
Programação de sockets
●
101
Cliente/Servidor UDP
Servidor (US.C)
MAIN()
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programaçã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
102
Programação de sockets
●
103
Cliente/Servidor UDP
Servidor (US.C)
MAIN()
Cliente (UC.C)
Mensagem /
IP Servidor
receber_parâmetros()
socket_servidor =
criar_socket(8888)
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
104
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 */
Programação de sockets
●
105
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);
Programação de sockets
●
106
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
107
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);
}
Programação de sockets
●
108
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
109
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);
}
Programação de sockets
●
110
Cliente/Servidor UDP
Servidor (US.C)
Cliente (UC.C)
Mensagem /
IP Servidor
socket_servidor =
criar_socket(8888)
receber_parâmetros()
socket_cliente = criar_socket(0)
Mensagem /
IP Servidor
receber_mensagem
(socket_servidor, mensagem)
mensagem
enviar_mensagem
(socket_cliente, IP_servidor,
porta_servidor, mensagem)
mensagem
enviar_mensagem
(socket_servidor, IP_cliente,
porta_cliente mensagem)
mensagem
receber_mensagem
(socket_cliente, mensagem)
fechar_socket, socket_cliente)
Programação de sockets
●
111
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);
}
Programação de sockets
●
112
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
113
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programaçã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
114
Programaçã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
115
Programaçã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 */
}
116
Programação de sockets
●
117
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
118
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);
Programação de sockets
●
119
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programaçã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);
}
120
Programação de sockets
●
121
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
122
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);
Programação de sockets
●
123
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
124
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);
Programação de sockets
●
125
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programaçã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
126
Programaçã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
127
Programação de sockets
●
128
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 */
Programação de sockets
●
129
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);
}
Programação de sockets
●
130
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
Cliente/Servidor TCP (Cliente – criar_socket)
131
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);
}
Programação de sockets
●
132
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
133
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);
}
Programação de sockets
●
134
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programaçã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);
}
135
Programação de sockets
●
136
Cliente/Servidor TCP
Servidor (TS.C)
mensagem / Cliente (TC.C)
IP Servidor
Receber parâmetros
sock = criar_socket(0)
sock = criar_socket(9999)
socket_cliente =
aceitar_conexao(sock)
conexão
conectar_com_servidor
(sock,IP,9999)
mensagem
receber_mensagem
(mensagem,socket_cliente)
mensagem
enviar_mensagem
(mensagem,sock)
mensagem
enviar_mensagem
(mensagem,socket_cliente)
mensagem
receber_mensagem
(mensagem,sock)
Programação de sockets
●
137
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);
Programação de sockets
●
Testem os programas!
●
Vejam como eles funcionam!
●
Coloquem mensagens de instrumentação no código para acompanhar os
passos!
138
139
Capítulo 2 - FIM
Download

Programação de sockets