csocketsunix-socketposix-select

Weird order after select() (with FD_SET())


I am developing a multi-client Unix Domain Socket to transfer data through multiple processes. I found some code that implements chat between every client and stuff but I want that once a client send something to the server, the server reply back and the client disconnect.

Having that said, I don't want while(fgets()) but I want (on client side):

int main() {
    int sockfd;
    struct sockaddr_un remote;
    fd_set readfds;
    char buf[1024];
    char buf2[1024];
    int len;

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

    remote.sun_family = AF_UNIX;
    strcpy(remote.sun_path, SOCK_PATH);
    len = strlen(remote.sun_path) + sizeof(remote.sun_family);

    if(connect(sockfd, (struct sockaddr*)&remote, len) == -1)
        /* handle error */

    FD_ZERO(&readfds);
    FD_SET(0, &readfds);
    FD_SET(sockfd, &readfds);

    if(select(sockfd+1, &readfds, NULL, NULL, NULL) == -1)
        /* handle error */

    if(FD_ISSET(0, &readfds)) {
        fgets(buf, 1024, stdin);
        if(write(sockfd, buf, 1024) <= 0)
            /* handle error */
    }

    if(FD_ISSET(sockfd, &readfds)) {
        if(read(sockfd, &buf2, 1024) <= 0)
            /* handle error */
    }

    printf("%s\n", buf2);

    close(sockfd);
}

In this order, it works if I do everything after connect() twice (with a loop) but I want to do it only once. Without this loop, my server (which is a daemon) crash and I don't know why.

Furthermore, I added printf() from the code above to understand how it works:

(...)
printf("before select\n");
fflush(stdout);

if(select(sockfd+1, &readfds, NULL, NULL, NULL) == -1)
    /* handle error */

printf("before select\n");
fflush(stdout);

if(FD_ISSET(0, &readfds)) {
    fgets(buf, 1024, stdin);
    if(write(sockfd, buf, 1024) <= 0)
        /* handle error */
}
(...)

And I have this output:

before select
"input to fgets"
after select

And I don't understand why I have the input BEFORE "after select". It doesn't make any sense to me since I call fgets() after printf().

I hope this is understandable enough. What's wrong with my code ? Did I miss something ?


Solution

  • The first time through, you call select() before the server has responded. The result is that sockfd won't be ready for reading.

    In your case, the client might not need select() on the sockfd. You know that if you wrote something to the server you want to wait for the reply, right?