MC833A - 2019
Programação de Redes de Computadores

Exercício 2 - Parte 2: Servidor TCP concorrente

Critérios para entrega do exercício
Atividade
Passos:
  1. Adicione a função sleep no servidor.c da atividade prática anterior antes do socket ser fechado close(connfd) de modo que o servidor ''segure'' a conexão do primeiro cliente que se conectar.
    Com essa modificação, o servidor aceita a conexão de dois clientes de forma concorrente ?(realize o teste) Por que? (Este código não precisa ser enviado por email)
  2. Escreva, utilizando sockets TCP, um programa cliente e um programa servidor de echo que possibilitem a execução remota de comandos enviados pelo cliente. Lembre-se que o servidor deve atender a vários clientes de forma concorrente. O servidor deve receber como argumento na linha de comando a porta na qual irá escutar. O cliente deve receber como argumento na linha de comando o endereço IP do servidor e a porta na qual irá conectar.
  3. Detalhes do funcionamento:

    O que deve ser exibido:

    Detalhes da implementação:

  4. Modifique os programas do passo 2 de modo a imprimir no lado do cliente a saída da execução do comando e no lado do servidor a informação de quais clientes estão executando quais comandos. Além disso o servidor deve logar em um arquivo as informações referentes ao instante em que cada cliente conecta e desconecta.

  5. Detalhes das modificações:

    Os detalhes da implementação do Passo 2 continuam valendo.

  6. No trecho de código abaixo, que muito provavelmente estará presente nos códigos que você implementou, porque o servidor continua escutando e os clientes continuam com suas conexões estabelecidas mesmo após as chamadas dos Close? Explique o porque do uso de cada close e se algum deles está "sobrando" neste trecho de código.
  7.       for (;;) {
             connfd = Accept (listenfd,...);
    
             if ( (pid=Fork()) == 0) {
                Close(listenfd);
                doit(connfd); // Faz alguma operação no socket
                Close(connfd);
                exit(0);
             }
             Close(connfd);
          }
          
  8. Com base ainda no trecho de código acima, é correto afirmar que os clientes nunca receberão FIN neste caso já que o servidor sempre ficará escutando (LISTEN)? Justifique.
  9. Comprove, utilizando ferramentas do sistema operacional, que os processos criados para manipular cada conexão individual do servidor aos clientes são filhos do processo original que foi executado.
  10. Utilizando ferramentas do sistema operacional, qual dos lados da conexão fica no estado TIME_WAIT após o encerramento da conexão? Isso condiz com a implementação que foi realizada? Justifique.


Dicas: https://beej.us/guide/bgnet/html/multi/
	 /////////////////////////////// 
	 // Implementacao getsockname() 
	 // http://man7.org/linux/man-pages/man2/getsockname.2.html 
	 // https://beej.us/guide/bgnet/html/multi/inet_ntopman.html 
	 /////////////////////////////// 
	
	 struct sockaddr_in servaddr, my_addr;
	 char myIP[16];
	
	 // ...
	
	 int len = sizeof(my_addr);
	 bzero(&my_addr, sizeof(my_addr));
	 getsockname(sockfd, (struct sockaddr *) &my_addr, &len);
	 inet_ntop(AF_INET, &my_addr.sin_addr, myIP, sizeof(myIP));
	 printf("Local IP address: %s\n", myIP);
	 printf("Local Port : %u\n", ntohs(my_addr.sin_port));
	

	///////////////////////////////
	// Implementacao getpeername()
	// http://man7.org/linux/man-pages/man2/getpeername.2.html
	// https://beej.us/guide/bgnet/html/multi/syscalls.html#getpeername
	///////////////////////////////

	struct sockaddr_in servaddr, peer_addr;

	// ...

	bzero(&peer_addr, sizeof(peer_addr));
	len = sizeof(peer_addr);
	getpeername(connfd, (struct sockaddr*)&peer_addr, &len);
	printf("Peer IP address: %s\n", inet_ntoa(peer_addr.sin_addr));
	printf("Peer Port      : %d\n", ntohs(peer_addr.sin_port));
	

Instituto de Computação
Universidade Estadual de Campinas
Av Albert Einstein 1251
13083-852 Campinas, SP - Brazil