0

I have a unix domain socket program, the client try to connect to the server and send a message, when the server accept the client and read the message,it will sleep for 5 seconds and send another message.During the 5 seconds if I use ctrl+c to kill the client,then the server will quit.How can I handle this situation?My program as follows:

client:

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>

#define INFO_SERVER_PATH "/var/info_server_path"


int create_route_client()
{
    int client_fd;
    int addr_len;

    struct sockaddr_un server_addr;

    if ((client_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
        perror("create route info client socket");
        return -1;
    }

    memset(&server_addr, 0, sizeof(struct sockaddr_un));
    server_addr.sun_family = AF_LOCAL;
    strcpy(server_addr.sun_path, INFO_SERVER_PATH);
    addr_len = offsetof(struct sockaddr_un,sun_path) + strlen(server_addr.sun_path);

    if (connect(client_fd, (struct sockaddr*)&server_addr, addr_len) < 0) {
        perror("socket connect");
        return -1;
    }

    return client_fd;
}


int main(int argc, char const *argv[])
{

    char *sendline = "hello server";
    char recvline[512];
    int client_fd;
    int nwrite;
    int nread;

    client_fd = create_route_client();
    assert(client_fd > 0);

    nwrite = write(client_fd, sendline, strlen(sendline));
    if (nwrite < 0) {
        perror("failed to send command to the info server");
        close(client_fd);
        return 1;
    }

    nread = read(client_fd, recvline, sizeof(recvline));
    if (nread < 0) {
        perror("failed to read route state");
        close(client_fd);
        return 1;
    }
    recvline[nread] = '\0';
    printf("%s\n", recvline);
    close(client_fd);

    return 0;
}

server:

#include <unistd.h>
 #include <stdio.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <string.h>
 #include <assert.h>
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdint.h>

 #define INFO_SERVER_PATH "/var/info_server_path"
 int create_command_server()
 {
    struct sockaddr_un server_addr;
    size_t addr_len;
    int server_fd;

    if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        perror("create socket");
        return -1;
    }
    unlink(INFO_SERVER_PATH);

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, INFO_SERVER_PATH);
    addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(INFO_SERVER_PATH);

    if (bind(server_fd, (struct sockaddr*)&server_addr, addr_len) < 0) {
        perror("socket bind");
        return -1;
    }

    if (listen(server_fd, 1) < 0) {
        perror("socket listen");
        return -1;
    }

    return server_fd;
}

int main(int argc, char const *argv[])
{
    int info_server_fd = create_command_server();
    char recvline[512];
    char *sendline = "hello client";
    int nread;
    int nwrite;

    while (1) {
        int info_client_fd = accept(info_server_fd, NULL, NULL);
        nread = read(info_client_fd, recvline, 512);

        if (nread) {
            int i;
            for (i = 0; i < 5; i++) {
                printf("i = %d\n", i);
                sleep(1);
            }
            nwrite = write(info_client_fd , sendline, strlen(sendline));
            printf("nwrite = %d\n", nwrite);
            if (nwrite < 0) 
                perror("failed to send to client");

        }
        close(info_client_fd);
    }


    return 0;
}
bigpotato
  • 211
  • 2
  • 3
  • 13
  • 1
    There is no 'sleep for 5 seconds' in this code. Nor is there anything that would cause the server to exit. Nor is there any proper error checking, or end-of-stream checking, on the accepted socket. It isn't clear from your question whether it is the server or the client that should sleep, nor whether what you describe is what you want to happen or what is already happening that you don't want. – user207421 Apr 18 '14 at 04:23
  • 1
    You need to provide more information. When you say 'quits' what exactly does it exit because of? SIGPIPE? – caskey Apr 18 '14 at 04:54
  • to EJP: this is what I used to let server sleep for 5 seconds for (i = 0; i < 5; i++) { printf("i = %d\n", i); sleep(1); } – bigpotato Apr 18 '14 at 06:14
  • to caskey: 'quits' means the server process quits,it should run forever in a while(1) loop to accept clients and send messages back – bigpotato Apr 18 '14 at 06:16
  • So you've resolved one of my six issues with your question. – user207421 Apr 18 '14 at 06:43

1 Answers1

0

Hard to tell exactly without compiling and running your code, but I'd guess you're getting a SIGPIPE signal due to writing to the connection that was closed when you killed the client. The default action for a process receiving SIGPIPE is to terminate the process.

You can block the SIGPIPE signal using sigprocmask(), or tell the kernel you want to block it, ignore it or register an asynchronous signal handler for it using sigaction(). Then, when you call write(), it will return -1 and errno will be set to EPIPE. See the man page for write() http://man7.org/linux/man-pages/man2/write.2.html.

See the man page for signals http://man7.org/linux/man-pages/man7/signal.7.html for more information on signals and how to handle them. But, be warned that handling signals should not be done using an asynchronous signal handler unless you are very very careful and know exactly what you are doing. This is the source of many bugs. It's safest (by far) to ignore them if you don't need them, or block them and use a synchronous signal handling approach, like sigwait() or a signal fd (Linux-specific). In your case, you don't need them. The write() call will tell you when the connection is gone.

jtchitty
  • 358
  • 3
  • 7