FIN TCP non envoyé en faisant ‘close ()’ pour un client TCP multi-thread

J’ai écrit ci-dessous un client TCP multi-thread qui génère en principe un thread séparé pour recevoir les données, mais les données sont en cours d’écriture dans le thread principal uniquement après avoir pris une entrée de l’utilisateur en entrée standard.

Maintenant, après avoir appuyé sur ctrl ^ D, l’implémentation sort de la boucle (autour de l’appel getline ()) et ferme le descripteur de socket, mais aucun FIN n’est visible sur le fil. Cependant, remplacer close () par shutdown () fait la différence. Avec close (), aucune FIN n’est envoyée sur le fil, mais avec shutdown (fd, SHUT_WR), FIN est envoyée sur le fil?

Pourquoi cette différence?

#include  #include  #include  #include  #include  #include  #include  void *receiver (void *arg); pthread_t thrid; int sockfd; int reUse = 0; int main (int argc, char *argv[]) { struct sockaddr_in servaddr; struct sockaddr_in clntaddr; char *line; size_t len = 0; size_t read; int bytes; if (argc < 6) { printf ("Usage:%s      [Client IPv4 address] [Client Port]\n", argv[0]); return -1; } /* * AF_INET, AF_INET6, AF_UNIX, AF_NETLINK * SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_RAW */ if ((sockfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { printf ("Failed to create socket: %s\n", strerror (errno)); return -1; } /* * set SO_REUSEADDR option for the UDP server socket */ reUse = atoi (argv[3]); if (reUse) { int i = 1; setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof (i)); } bzero (&clntaddr, sizeof (struct sockaddr_in)); if (argc == 8) { printf ("doing bind......\n"); clntaddr.sin_family = AF_INET; clntaddr.sin_port = htons (atoi (argv[7])); inet_aton (argv[6], &clntaddr.sin_addr); if (bind (sockfd, (struct sockaddr *) &clntaddr, sizeof (struct sockaddr_in)) == -1) { perror ("Failed to bind"); close (sockfd); return -1; } } bzero (&servaddr, sizeof (struct sockaddr_in)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons (atoi (argv[2])); inet_aton (argv[1], &servaddr.sin_addr); if (-1 == connect (sockfd, (struct sockaddr *) &servaddr, sizeof (struct sockaddr_in))) { printf ("Failed to connect: %s\n", strerror (errno)); return -1; } if (pthread_create (&thrid, NULL, receiver, NULL) < 0) { printf ("Failed to create thread\n"); } while ((read = getline (&line, &len, stdin)) != -1) { bytes = send (sockfd, line, len, 0); if (bytes < 0) { if (errno == EINTR) continue; else printf ("%Read error %s\n", pthread_self (), strerror (errno)); } } if (0 == atoi (argv[4])) { printf ("doing close()....\n"); close (sockfd); } else if (1 == atoi (argv[4])) { printf ("doing shutdown(..., SHUTRD)....\n"); shutdown (sockfd, SHUT_RD); } else if (2 == atoi (argv[4])) { printf ("doing shutdown(..., SHUTWR)....\n"); shutdown (sockfd, SHUT_WR); } else if (3 == atoi (argv[4])) { printf ("doing shutdown(..., SHUTRDWR)....\n"); shutdown (sockfd, SHUT_RDWR); } if (line) free (line); sleep (atoi (argv[5])); } void * receiver (void *arg) { char buff[512]; int bytes; while (1) { bytes = recv (sockfd, buff, sizeof (buff), 0); if (bytes < 0) { if (errno == EINTR) continue; else printf ("%Read error %s\n", pthread_self (), strerror (errno)); pthread_exit (-1); } else if (bytes == 0) { printf ("connection closed by Peer\n"); close(sockfd); pthread_exit (-1); } else { printf ("Msg Received:%s\n", buff); } } } 

La fermeture d’appel (WR) enverra le message FIN, mais la fermeture n’aura guère de différence: si le nombre de références fd n’est pas égal à 0, il n’enverra pas le message FIN.

vous pouvez utiliser shutdown (socket, SHUT_WR) avant close (socket)