Introdução à Programação com Sockets Fernando Jorge Silveira Filho Daniel Sadoc Menasché

Slides:



Advertisements
Apresentações semelhantes
Python: Entrada e Saída
Advertisements

E/S Síncrona x E/S Assíncrona no sistema Unix
Interações cliente/servidor usando o UDP
Sockets Marco Antonio – marcoreis.net Arquiteto de Software Dezembro/2007.
Comunicação entre processos distribuídos
Bruno Rafael de Oliveira Rodrigues
Ir p/ primeira página Cliente/Servidor Modelo usado para construir aplicações Servidor em número de porta conhecido – Aceita requisições e executa serviços.
Algoritmos e Estrutura de Dados I
Programação com sockets API Sockets apareceu no BSD4.1 UNIX em 1981 são explicitamente criados, usados e liberados por aplicações paradigma cliente/servidor.
O conceito de socket Uma comunicação entre dois processos via TCP (ou UDP) é identificada unívocamente por dois pares de valores, que denotam os dois pontos.
Interação Cliente Servidor
Prof. Luis Otavio Alvares
Conceitos de Sockets Universidade Federal do Rio Grande do Sul (UFRGS)
LPG - I: Ponteiros e Vetores/Matrizes UDESC - SBS
UNIX.
Tratamento de Ficheiros
FEUPDEECRedes de Computadores, 4º Ano de EEC, ramo de ACI Sockets Abril, 98Isidro Vila Verde 1 Formato das estruturas de dados Estrutura.
Prof. Edmundo R. M. Madeira Carlos R. Senna MC823 Laboratório de Teleprocessamento e Redes Primeiro Semestre 2007.
Revisão da Linguagem C.
Camada de Transporte: Portas, Sockets, Aplicações em Rede
REDES DE COMPUTADORES II
Modelo de referência OSI
Prof. Natalia Castro Fernandes Mestrado em Telecomunicações – UFF 2º semestre/2012.
PROGRAMAÇÃO ESTRUTURADA II
Ordenação e Pesquisa de Dados Marco Antonio Montebello Júnior
CADEIA DE CARACTERES (Strings)
Comunicação entre processos usando Sockets
Estrutura de dados II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
DAVID ANDERSON CARDOSO DANTAS
Aula Prática 12 Operações com Arquivos Monitoria
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática Disciplina: Estrutura de Dados Professor: Cheli dos S. Mendes da Costa Arquivo.
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Comunicação entre Processos - Sockets. Conceitos Básicos Sockets são uma forma de IPC ( InterProcess Communication ) fornecida pela 4.3 BSD que fornecem.
Estruturas de Dados Aula 2: Estruturas Estáticas 07/04/2014.
Concorrência e thread Petrônio Júnior(pglj) Márcio Neves(mmn2)
Educação Profissional Técnica de Nível Médio Curso Técnico de Informática
Capítulo V – Comandos de Entrada e Saída 5.1 – Equipamentos de entrada e saída 5.2 – Saída no vídeo-texto 5.3 – Entrada pelo teclado 5.4 – Entrada e saída.
Programação distribuída e concorrente
1 Comunicação Inter-Processos -> RMI -> RPC -> TCP -> UDP (Abstração de passagem de mensagem)
MODELO DE REFERÊNCIA TCP/IP
Transmissão de Dados O Modelo de Referência TCP/IP
Operações com Arquivos Monitoria A estrutura FILE  É como um tipo de dado, mas não é um tipo propriamente dito  Definido no arquivo cabeçalho.
Estruturas de Dados Aulas 3 e 4: Uso da memória e Vetores
Desenvolvimento de Aplicações TCP/IP com Sockets Márcio de Sousa Dias
Aula Prática 11 Operações com Arquivos Monitoria
Programação de Computadores I – Arquivos
Arquitetura de Redes de Computadores – Luiz Paulo Maia Camada de Transporte1 Arquitetura de Redes de Computadores Luiz Paulo Maia Camada de Transporte.
Linguagem de programação I A Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação Versão: _01.
CES-10 INTRODUÇÃO À COMPUTAÇÃO
Administração e Projeto de Redes
Comunicação Cliente-Servidor Linguagem para Internet II Prof. Marcelo da Silveira Siedler SERVIÇO NACIONAL DE APRENDIZAGEM COMERCIAL.
Algoritmos e Programação MC102 Prof. Paulo Miranda IC-UNICAMP Aula 15 Ponteiros.
Redes de computadores: Aplicações Prof. Dr. Amine BERQIA
Arquitetura TCP/IP Aplicação Transporte Rede Enlace Física.
Programação Computacional Aula 8: Entrada e Saída pelo Console Prof a. Madeleine Medrano
Camada de Aplicação Prof. Horácio. Objetivo Apresentar os detalhes específicos dos tipos de aplicação; Apresentar o modelo cliente-servidor; Apresentar.
Ponteiros em C Prof. Kariston Pereira
Estrutura de Dados Revisão Professor Luiz José Hoffmann Filho
Linguagem de Programação
Protocolos de Comunicação e Passagem de Mensagens
Sockets Redes de Comunicação de Dados Prof. Esp. Cristiano José Cecanho.
USP – ICMC – SSC SSC0300 2º Semestre 2015 Disciplina de Linguagem de Programação e Aplicações [ Eng. Elétrica / Eletrônica ] 1 Prof. Dr. Daniel Rodrigo.
Programação II Arquivos Autoria: Ernani Santos Modificação: Clebson Oliveira Adaptação: Claudia Boeres.
2: Application Layer 1 Capítulo 2: Camada de Aplicação  2.1 Princípios da camada de aplicação  2.2 Web e HTTP  2.3 FTP  2.4  SMTP, POP3, IMAP.
Redes de Computadores Prof. Msc. Moisés Pereira Bastos.
Alocação Dinâmica Dilvan Moreira. Objetivos  Entender o que são e como usar:  Gerenciamento de Memória  Alocação Dinâmica em C.
Curso Superior em Redes de Computadores Camada de Aplicação Prof. Sales Filho.
FUNÇÕES Dilvan Moreira (baseado em material de Z. Liang)
Fundamentos de Programação 1 Slides 18 Prof. SIMÃO Jean Marcelo SIMÃO Linguagem C “Arquivos Seqüências ou de Texto ”. 1.
Soquetes (1) SOCKET Uma interface local, criada por aplicações, ponto final de comunicação no qual os processos de aplicação podem tanto enviar quanto.
Transcrição da apresentação:

Introdução à Programação com Sockets Fernando Jorge Silveira Filho Daniel Sadoc Menasché

Visão Geral Objetivos: – Realizar comunicação entre processos. – Entender como usar as funções da API sockets. Histórico da API sockets: desenvolvida na época da implementação dos protocolos TCP/IP pelo grupo da UC, Berkeley. Inicialmente iremos (re)ver alguns conceitos que serão importantes.

Rotinas do S.O. Sockets Comandos no Hardware Rotinas do Driver API Sockets Application Program Interface – elemento de ligação entre a aplicação e um sistema de mais baixo nível. Aplicação Transporte Rede Enlace de Dados Física Sistema Operacional (Kernel) Drivers e Hardware Aplicação Final

Conceitos Importantes Argumentos de Valor/Resultado Descritores de Arquivo Chamadas de Sistema de E/S Byte Ordering Portas e Endereços IP Associações & Conexões Serviços de Transporte

Argumentos de Valor/Resultado É possível (e comum) na linguagem C, utilizar o recurso de passagem de argumentos por referência para passar valores para uma função ao mesmo tempo em que se espera um valor de retorno na mesma variável. Exemplo: imagine uma função is_prime() que retorna 1 se um número apontado por um ponteiro n é primo e 0 (zero) se composto. Neste último caso, a função também retorna o número primo mais próximo do valor passado. Este segundo valor de retorno pode ser colocado no próprio endereço de memória referenciado por n. int is_prime( int * n ) { /* verifica se (*n) é primo e em caso negativo coloca o primo mais próximo em (*n) */ }

Descritores de Arquivos Números inteiros não negativos que são ponteiros para estruturas de dados do sistema que representam os arquivos abertos por um processo x Descritores de Arquivo y z Imagem do ProcessoEstruturas do S.O. z z

Chamadas de Sistema de E/S Operações básicas que podem ser realizadas com arquivos. open, close, read, write. #include int open( const char * filename, int oflag,... ); int close( int fd ); size_t read( int fd, void * buffer, size_t n_bytes ); size_t write( int fd, void * buffer, size_t n_bytes );

Como um valor é armazenado na memória? Exemplo: = 0x Para evitar conflitos entre hosts de arquiteturas diferentes é convencionado que informações de controle na rede são armazenadas em Big-Endian. Byte Ordering Big-EndianLittle-Endian n n+1 n+2 n+3 EndereçoMemória n n+1 n+2 n+3 EndereçoMemória

Endereços IP e Portas Endereços IP identificam hosts na rede TCP/IP e são formados por 4 bytes, normalmente chamado octetos por razões históricas. Portas são identificadores dos processos interessados em usar os recursos de rede em um host. Portas ocupam 2 bytes na memória. Ambos tipos de variáveis são armazenadas no byte order da rede (Big-Endian) A40A029C36 Notação Padrão Hexadecimal

Associações Um processo precisa associar um socket a um endereço para “avisar” ao sistema operacional que deseja receber dados que chegam ao host com o endereço de destino especificado Processos : : : 20 Endereço Associado Sockets Processos : : : : 56 Endereço Associado Sockets

Conexões Um socket pode ser conectado a um endereço diferente do seu próprio para que pacotes possam ser enviados por ele diretamente ao processo parceiro. 602 Processo 20 Endereço Associado Socket : Endereço Conectado : 13003

Serviços de Transporte A camada de transporte dos protocolos TCP/IP fornece duas opções de tipos de serviço: – Serviço orientado a conexão: utiliza o protocolo TCP (Transmission Control Protocol) e garante entrega e ordenação. – Serviço datagrama: utiliza o protocolo UDP (User Datagram Protocol) e não faz nenhuma garantia.

Esquema de uma Aplicação TCP Um par de aplicações que se comunicam por TCP em geral tem a seguinte forma: accept( ) close( ) connect( ) socket( ) bind( ) listen( ) close( ) Estabelecimento da Conexão TCP Cliente Servidor writen( ) readn( ) writen( ) readn( )

Esquema de uma Aplicação TCP Um par de aplicações que se comunicam por TCP em geral tem a seguinte forma: accept( ) close( ) connect( ) socket( ) bind( ) listen( ) close( ) Estabelecimento da Conexão TCP Cliente Servidor writen( ) readn( ) writen( ) readn( ) ter telefone associar número ao telefone ligar alarme responder chamada fazer chamada

Sockets - Criação Utiliza-se a chamada de sistema socket() : Parâmetros: – domain – o tipo de rede do socket. Usamos AF_INET (Address Family Internet). Outros tipos: AF_LOCAL, AF_INET6. – type – o tipo de serviço de transporte. Para sockets TCP usamos SOCK_STREAM, para UDP usamos SOCK_DGRAM. – protocol – o protocolo utilizado. Passando 0 (zero) é utilizado o padrão. A função retorna um descritor do socket criado ou –1 em caso de erro. #include int socket( int domain, int type, int protocol );

Sockets - Endereços Endereços IP e portas são armazenados em estruturas do tipo struct sockaddr_in. sin_family é o tipo do endereço. AF_INET deve ser usado. sin_port é a porta associada ao endereço. sin_addr é uma estrutura que contém o endereço IP (os 4 octetos). O endereço IP e a porta devem ser armazenados no byte order da rede (Big- Endian). #include struct sockaddr_in { sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; /*... outros campos */ }; struct in_addr { in_addr_t s_addr; }; uint16 htons( uint16 data_in_host_order ); uint16 ntohs( uint16 data_in_net_order ); uint32 htonl( uint32 data_in_host_order ); uint32 ntohl( uint32 data_in_net_order );

Sockets - Associação Utiliza-se a chamada de sistema bind() : Parâmetros: – sockfd – o descritor do socket. – my_addr – a estrutura com o endereço para ser associado. – addrlen – o tamanho da estrutura do endereço. A função retorna 0 (zero) em caso de sucesso ou –1 no caso de um erro. Erro comum: EADDRINUSE (“Address already in use”) #include int bind( int sockfd, struct sockaddr *my_addr, socklen_t addrlen );

Sockets – Traduzindo Endereços IP Para converter um endereço IP entre as formas de string e binária: A função inet_aton() converte um endereço na notação do ponto ( ) para o formato binário em byte order de rede (como a struct sockaddr_in espera) e retorna 0 (zero) em caso de sucesso. A função inet_ntoa() faz a conversão oposta. #include int inet_aton(const char * str, struct in_addr * addrptr); char * inet_ntoa(struct in_addr addr);

Sockets – Resolvendo Nomes com DNS Para resolver nomes de hosts ( para endereços IP ( ) usamos as rotinas de acesso ao serviço DNS: #include struct hostent * gethostbyname(const char * str); struct hostent { int h_length; /* tamanho do endereço */ char **h_addr_list; /* lista de endereços */ char *h_addr; /* primeiro endereço */ /*... outros campos */ }

Sockets TCP Sockets orientados a conexão com garantias de entrega e ordenação. É preciso estabelecer a conexão antes da troca de dados. O servidor cria um socket especial para “escutar” pedidos de conexão do cliente. Cada vez que o servidor aceita um pedido de conexão recebido no socket de escuta, um novo socket é criado para realizar a comunicação. Assim é possível para o servidor voltar a aceitar novos pedidos de conexão mais tarde (usando o socket de escuta).

Sockets TCP – listen() Para por um socket em modo de escuta usamos a chamada de sistema listen() : Parâmetros: – sockfd – o descritor do socket. – backlog – a soma das filas de conexões completas e incompletas. Este parâmetro é extremamente dependente da implementação do Sistema Operacional. O valor de retorno da função é 0 (zero) em caso de sucesso ou –1 caso contrário. #include int listen( int sockfd, int backlog );

Sockets TCP – accept() Esta função aceita pedidos de conexão pendentes ou fica bloqueada até a chegada de um. Parâmetros: – sockfd – o descritor do socket. – cliaddr – a estrutura onde será guardado o endereço do cliente. – addrlen – argumento valor/resultado com o tamanho da estrutura do endereço. O valor de retorno da função é um novo descritor (não negativo) em caso de sucesso ou –1 caso contrário. Cada novo descritor retornado por accept() está associado à mesma porta do socket de escuta. #include int accept( int sockfd, struct sockaddr * cliaddr, socklen_t * addrlen );

Sockets TCP – send() Usada para enviar dados por um socket conectado. Parâmetros: – sockfd – o descritor do socket. – buffer – um ponteiro para os dados a serem enviados. – n_bytes – quantidade de bytes a serem enviados a partir do ponteiro buffer. – flags – opções para essa operação. O valor de retorno da função é a quantidade de bytes enviados em caso de sucesso ou –1 caso contrário. #include int send( int sockfd, void * buffer, size_t n_bytes, int flags );

Sockets TCP – recv() Recebe dados por um descritor conectado, ou bloqueia a execução até que algum dado chegue ao socket: Parâmetros: – sockfd – o descritor do socket. – buffer – um ponteiro para a área de memória onde devem ser armazenados os dados recebidos. – n_bytes – quantidade máxima de bytes a serem recebidos. – flags – opções para essa operação. O valor de retorno da função é a quantidade de bytes recebidos em caso de sucesso ou –1 caso contrário. #include int recv( int sockfd, void * buffer, size_t n_bytes, int flags );

Atenção para uma Armadilha! As funções read, recv, recvfrom, write, send e sendto podem retornar menos bytes do que a quantidade requisitada, e nenhuma mensagem de erro é retornada neste caso! Solução: ao usar as funções r ecv, recvfrom, send e sendto pode-se (deve- se!) passar como parâmetro a flag MSG_WAITALL.

Atenção para uma Armadilha! As funções read e write não devem ser utilizadas! Ao invés disto, deve-se usar as funções de “embrulho” (“wrap functions”) readn e writen. ssize_t readn(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nread; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( ( nread = read ( fd, ptr, nleft ) ) <=0 ) { if (errno == EINTR) nread = 0; else return (-1); } else if ( nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return (n - nleft); }

#include int main( int argc, char ** argv ) { int sockfd; char recvline[30]; struct sockaddr_in servaddr; if( argc != 2 ) return –1; sockfd = socket( AF_INET, SOCK_STREAM, 0 ); memset( &servaddr, 0, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(12345); inet_aton( argv[1], &servaddr.sin_addr ); connect( sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr) ); readn( sockfd, recvline, 30 ); fputs( recvline, stdout ); close( sockfd ); return 0; } Exemplo – Um Cliente TCP Inicializar a estrutura servaddr com zeros. Preencher os campos da estrutura servaddr :  sin_family com o tipo de endereço (AF_INET)  sin_port com a porta (12345) no byte order da rede.  sin_addr com o endereço passado como argumento para o programa. Conecta o socket com o endereço do servidor ( servaddr ). Isto irá estabelecer a conexão TCP entre o cliente e o servidor. Lê 30 bytes do socket. Esta função pode ler menos bytes se o outro lado (o servidor) fechar a conexão. Imprime os dados recebidos na saída padrão. Fecha o socket. Criar um socket para rede TCP/IP ( AF_INET ), orientado a conexão ( SOCK_STREAM ), usando TCP (o protocolo padrão dado por 0 ).

#include int main( int argc, char ** argv ) { int listenfd, connfd, size; struct sockaddr_in myaddr, cliaddr; listenfd = socket( AF_INET, SOCK_STREAM, 0 ); memset( &myaddr, 0, sizeof(myaddr) ); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(12345); myaddr.sin_addr.s_addr = INADDR_ANY; bind( listenfd, (struct sockaddr *)&myaddr, sizeof(myaddr) ); listen( listenfd, 5 ); for( ; ; ) { memset( &cliaddr, 0, sizeof(cliaddr) ); size = sizeof( cliaddr ); connfd = accept( listenfd, (struct sockaddr *)&cliaddr, &size ); writen( connfd, “Alo Mundo”, 10 ); close( connfd ); } return 0; } Preencher a estrutura do endereço local ( myaddr ) para associação com o socket:  sin_addr contém o endereço IP pelo qual o processo deseja receber pacotes. Como uma máquina pode ter vários IPs, é mais prático especificar que se deseja receber pacotes para qualquer um deles. Para isso usamos a constante INADDR_ANY. Exemplo – Um Servidor TCP Associar o endereço preenchido com o socket, para informar o S.O. de que o processo deseja receber pacotes para este endereço. Aguarda um pedido de conexão. Envia uma mensagem de 10 bytes pelo socket. Fecha o socket da conexão. Volta a aceitar novos pedidos. Colocar o socket em modo de escuta. Isto cria uma fila de pedidos de conexão para o socket.

Servidores Concorrentes Muitas vezes é necessário para um servidor lidar com vários clientes de uma única vez. Para conseguir isto é preciso, de alguma maneira, voltar a aceitar conexões, sem esperar que um cliente seja completamente servido. Isto normalmente é feito através da criação de novas threads ou novos processos. Um servidor, após o retorno da função accept(), se divide em dois, e enquanto uma linha de execução se dedica a atender o cliente, outra volta a esperar por novos pedidos de conexão.

Servidores concorrentes Esquema de um Servidor Típico pid_t pid; int listenfd, confd; listenfd = socket(...); bind(listenfd,...); listen(listenfd, LISTENQ); for( ; ; ) { connfd = accept(listenfd,...); if ( ( pid = fork() ) == 0 ) { close(listenfd); doit(connfd); close(connfd); exit(0) } close (connfd); }

Conclusões sobre sockets TCP Um par de aplicações que se comunicam por TCP em geral tem a seguinte forma: accept( ) close( ) connect( ) socket( ) bind( ) listen( ) close( ) Troca de Dados Estabelecimento da Conexão TCP Cliente Servidor Servidores Concorrentes

Sockets UDP Sockets sem conexão e sem garantias de entrega ou ordenação. Só é preciso saber o endereço de destino antes de enviar dados. É possível receber dados a qualquer momento e de qualquer um. Usamos as funções sendto() e recvfrom(). Pode-se ainda usar a função connect() com sockets UDP, mas o seu significado aqui é diferente, uma vez que NÃO faz sentido falar em uma conexão UDP. Para sockets UDP, a função connect() apenas “fixa” o endereço conectado. Assim é possível usar as funções send() e recv() como para sockets TCP.

Sockets UDP – sendto() Envia dados por um socket NÃO conectado. Parâmetros: – sockfd – o descritor do socket. – buffer – um ponteiro para os dados a serem enviados. – n_bytes – quantidade de bytes a serem enviados. – flags – opções para essa operação. – to – endereço de destino dos dados. – addrlen – tamanho em bytes do endereço de destino. O valor de retorno da função é a quantidade de bytes enviados em caso de sucesso ou –1 caso contrário. #include int sendto( int sockfd, void * buffer, size_t n_bytes, int flags, const struct sockaddr * to, socklen_t addrlen );

Sockets UDP – recvfrom() Recebe dados por um descritor NÃO conectado, ou bloqueia a execução até que algum dado chegue: Parâmetros: – sockfd – o descritor do socket. – buffer – um ponteiro para a área de memória onde devem ser armazenados os dados recebidos. – n_bytes – quantidade máxima de bytes a serem recebidos. – flags – opções para essa operação. – from – ponteiro para a estrutura onde será escrito o endereço de origem. – addrlen – argumento valor/resultado com o tamanho do endereço de origem. O valor de retorno da função é a quantidade de bytes recebidos em caso de sucesso ou –1 caso contrário. #include int recvfrom( int sockfd, void * buffer, size_t n_bytes, int flags, struct sockaddr * from, socklen_t * addrlen );

#include int main( int argc, char ** argv ) { int sockfd; struct sockaddr_in servaddr; if( argc != 2 ) return –1; sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); memset( &servaddr, 0, sizeof(servaddr) ); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(12345); inet_aton( argv[1], &servaddr.sin_addr ); sendto( sockfd, “Alo Servidor”, 13, MSG_WAITALL, (struct sockaddr *)&servaddr, sizeof(servaddr) ); close( sockfd ); return 0; } Exemplo – Um Cliente UDP Inicializar a estrutura servaddr com zeros. Preencher os campos da estrutura servaddr :  sin_family com o tipo de endereço (AF_INET)  sin_port com a porta (12345) no byte order da rede.  sin_addr com o endereço passado como argumento para o programa. Envia 13 bytes de dados para o servidor. Criar um socket para rede TCP/IP ( AF_INET ), orientado a datagramas ( SOCK_DGRAM ), usando UDP (o protocolo padrão dado por 0 ).

#include int main( int argc, char ** argv ) { int sockfd, size, n; struct sockaddr_in myaddr; sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); memset( &myaddr, 0, sizeof(myaddr) ); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(12345); myaddr.sin_addr.s_addr = INADDR_ANY; bind( sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr) ); for( ; ; ) { recvfrom( sockfd, recvline, 30, MSG_WAITALL, NULL, NULL ); fputs( recvline, stdout ); } return 0; } Exemplo – Um Servidor UDP Associar o endereço preenchido com o socket, para informar o S.O. de que o processo deseja receber pacotes para este endereço. Aguarda até 30 bytes. É possível para esta função retornar antes se o outro lado enviar um datagrama menor. Imprime os dados recebidos na saída padrão.

Conclusões sobre sockets UDP Um par de aplicações que se comunicam por UDP em geral tem a seguinte forma: close( ) socket( ) bind( ) close( ) Troca de Dados Cliente Servidor bind( )

Esta é a forma mais simples de depurar aplicações que envolvem sockets, threads e mais de um processo. Atenção! Deve-se gerar as mensagens de aviso em ‘stderr’ (que não possui buffer) e não ‘stdout’! Inconveniente desta técnica de depuração: pode afetar o funcionamento do programa. Depurando: Passo 0, Exibindo mensagens de aviso

Depurando: Passo 1, A Máquina de Estados Comando chave: netstat -a

src]$ netstat -a | grep Proto Local Address Foreign Address State tcp *:32568 *:* LISTEN tcp localhost:47415 localhost:32568 ESTABLISHED tcp localhost:32568 localhost:47415 ESTABLISHED src]$ netstat -a | grep tcp localhost:47415 localhost:32568 CLOSE_WAIT tcp localhost:32568 localhost:47415 FIN_WAIT2 Depurando: Passo 1, A Máquina de Estados do TCP Comando chave: netstat -a wildcard

tcpdump -x src host_name > log_file Programa equivalente, com interface gráfica: ethereal Depurando: Passo 2, O comando tcpdump Imprime o conteúdo de cada pacote, em hexadecimal Fonte dos pacotes

Lições Aprendidas

Bibliografia Recomendada Stevens, W. R. – UNIX Network Programming: Volume I – Networking APIs: Sockets and XTI Stevens, W.R. – TCP/IP Illustrated vol.1 Besaw, L. – BSD Sockets Reference (formato PostScript (.ps) em