Unix Sockets: client stops receiving messages correctly after first 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

      

I'm trying to make a simple chat application using Unix sockets:

After compiling the code, I first start the server on one terminal and it speaks while waiting for a connection. And then I run the client on another terminal on the same computer, it connects successfully. The client then sends the first message. The server receives it fine.

But after that, something strange happens. I have to enter multiple times to get it to work and get the whole message.

Here's a simple conclusion:

Server side

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

      

Client side

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

      

SingleWord // cleint sends this message to the server

Server side

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

      

Client side /// I had to click multiple times to get the whole message

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

      

Please help me solve the following:

The code is shown below.

Server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#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) perror("recv");
                    printf("error");
                    done = 1;
                }
                //m = fgets(str2,100,stdin);
                if (!done)
                    while (fgets(str2, 100, stdin) > 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 <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#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) {
                perror("send");
                exit(1);
            }
            if ((t = recv(s, str2, strlen(str2), 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;
}

      

+3


source to share


2 answers


You have a number of problems in your code:

  • server.c:

    • after n = recv(s2, str, 100, 0);

      , you don't null terminate str before using it - you should have:

      n = recv(s2, str, 100, 0);
      str[(n > 0) ? n : 0] = '\0';
      
            

    • while(1)

      it should be while (! done)

      if you get an error you get an infinite loop displaying the error - you should have:

      do {
          while (! done) {
      
            

  • client.c:

    • you are using strlen

      in recv

      on t = recv(s, str2, strlen(str2), 0)

      - it should be:

      if ((t = recv(s, str2, sizeof(str2), 0)) > 0) {
      
            

    • while (1) { while (printf("> "), fgets(str, 100, stdin), !feof(stdin))

      does not do what you expect if eof is on stdin, the outer loop continues - you can write (if int done = 0

      declared above):

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



And I do not guarantee that there are no other small problems of the same type, and you should multiplex the IO with select

, because at this point, the client and server should talk alternately.

+1


source


You may need to start a new thread in the client to receive a message from the server or by using I / O multiplexing.



-2


source







All Articles