Unix Sockets: le client cesse de recevoir les messages correctement après le premier message

Info

[root@xilinx Downloads]# uname -a Linux xilinx 2.6.32-71.el6.x86_64 #1 SMP Wed Sep 1 01:33:01 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux 

J’essaie de créer une application de chat simple en utilisant les sockets Unix:

Après avoir compilé le code, je lance d’abord le serveur sur un terminal et il dit, en attente de connexion. Et puis je lance le client sur un autre terminal sur le même ordinateur, il se connecte avec succès. Le client envoie alors le premier message. Le serveur le reçoit parfaitement.

Mais après cela, quelque chose de bizarre arrive. Je dois entrer plusieurs fois pour le faire fonctionner et obtenir le message entier.

Voici une sortie simple:

Du côté serveur

 [root@xilinx Downloads]# ./server Waiting for a connection... Connected. 

Côté client

 [root@xilinx Downloads]# [root@xilinx Downloads]# [root@xilinx Downloads]# ./client Trying to connect... Connected. 

SingleWord // cleint envoie ce message au serveur

Du côté serveur

 >received<SingleWord //server receives this- good. IamServer // Now server sends some message 

Côté client /// J’ai dû appuyer plusieurs fois sur Entrée pour obtenir le message entier

 echo> Ia> echo> mS> echo> er> echo> ve> echo> r 

S’il vous plaît aidez-moi à résoudre ce problème:

Le code est donné ci-dessous.

Serveur.c

 #include  #include  #include  #include  #include  #include  #include  #define SOCK_PATH "echo_socket" int main(void) { int s, s2, t, len; struct sockaddr_un local, remote; char str[100]; char str2[100]; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_PATH); unlink(local.sun_path); len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(s, (struct sockaddr * ) & local, len) == -1) { perror("bind"); exit(1); } if (listen(s, 5) == -1) { perror("listen"); exit(1); } for (;;) { int done, n; printf("Waiting for a connection...\n"); t = sizeof(remote); if ((s2 = accept(s, (struct sockaddr * ) & remote, & t)) == -1) { perror("accept"); exit(1); } printf("Connected.\n"); done = 0; do { while (1) { n = recv(s2, str, 100, 0); printf(">received<%s", str); if (n <= 0) { if (n  0) { if (send(s2, str2, strlen(str2), 0) < 0) { perror("send"); //if (send(s2, str2, m, 0) < 0) { //perror("send"); done = 1; } } } } while (!done); close(s2); } return (0); } 

Client.c

 #include  #include  #include  #include  #include  #include  #include  #define SOCK_PATH "echo_socket" int main(void) { int s, t, len; struct sockaddr_un remote; char str[100]; char str2[100]; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } printf("Trying to connect...\n"); remote.sun_family = AF_UNIX; strcpy(remote.sun_path, SOCK_PATH); len = strlen(remote.sun_path) + sizeof(remote.sun_family); if (connect(s, (struct sockaddr * ) & remote, len) == -1) { perror("connect"); exit(1); } printf("Connected.\n"); while (1) { while (printf("> "), fgets(str, 100, stdin), !feof(stdin)) { if (send(s, str, strlen(str), 0)  0) { str2[t] = '\0'; printf("echo> %s", str2); } else { if (t < 0) perror("recv"); else printf("Server closed connection\n"); exit(1); } } } close(s); return 0; } 

Vous avez un certain nombre de problèmes dans votre code:

  • server.c:

    • après le n = recv(s2, str, 100, 0); , vous ne devez pas mettre fin à str avant de l’utiliser – vous devriez avoir:

       n = recv(s2, str, 100, 0); str[(n > 0) ? n : 0] = '\0'; 
    • le while(1) devrait être un while (! done) , si vous obtenez une erreur, vous obtenez une boucle infinie affichant l’erreur – vous devriez avoir:

       do { while (! done) { 
  • client.c:

    • vous utilisez un strlen dans recv à t = recv(s, str2, strlen(str2), 0) – devrait être:

       if ((t = recv(s, str2, sizeof(str2), 0)) > 0) { 
    • le while (1) { while (printf("> "), fgets(str, 100, stdin), !feof(stdin)) ne fait pas ce que vous attendez, si eof sur stdin, la boucle externe continue – vous pouvez écrire (à condition que int done = 0 soit déclaré ci-dessus):

       while (! done) { done = 1; while (printf("> "), fgets(str, 100, stdin) != NULL) { done = 0; 

Et je ne garantis pas qu’il n’y a pas d’autres petits problèmes du même type, et vous devriez faire du multiplexage IO avec select car pour l’instant, le client et le serveur doivent parler chacun à leur tour.

Vous devrez peut-être démarrer un nouveau thread dans le client pour recevoir un message du serveur ou utiliser le multiplexage d’E / S.