Search code examples
cservermessagenonblocking

Reading consecutive messages


I have created a server and trying to listen on a specific port. When I am sending a message with netcat to this specific port, I succeed reading the first message, with the

read(fd_client_serv, buf, sizeof(buf));

system call. After that, any message sent will not be printed. Why is that happening?

Here is my code:

void start_server(void)
{

    int fd_serv, fd_client_serv, bytes_read;
    struct sockaddr_in client_serv_addr;
    char buf[2048];

    socklen_t sin_len_serv = sizeof(client_serv_addr);

    fd_serv = initialize_server(get_serving_port());
    fd_set_blocking(fd_serv, 0);

    while(1)
    {
        fd_client_serv = accept(fd_serv, (struct sockaddr *) &client_serv_addr, &sin_len_serv);

        puts("HA!!! you cannot block me!!!");
        sleep(2);
        memset(buf, 0, sizeof(buf));
        write(fd_client_serv, "thank you for answering", 30);
        bytes_read = read(fd_client_serv, buf, sizeof(buf));
        printf("%d\n", bytes_read);
        fflush(stdout);
        printf("%s\n", buf);
    }
}


int initialize_server(int port)
{

    struct sockaddr_in server_addr;

    int fd_temp;

    int on = 1;

    fd_temp = socket(AF_INET, SOCK_STREAM, 0);
    if (fd_temp < 0)
    {
        perror("socket");
        exit(1);
    }
    setsockopt(fd_temp, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    if (bind(fd_temp,(struct sockaddr *) &server_addr, sizeof(server_addr)) == -1)
    {
        perror("bind");
        close(fd_temp);
        exit(1);
    }
    if (listen(fd_temp, 10) == -1)
    {
        perror("listen");
        close(fd_temp);
        exit(1);
    }
    return fd_temp;
}


int fd_set_blocking(int fd, int blocking)
{
    /* Save the current flags */
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1)
        return 0;

    if (blocking)
        flags &= ~O_NONBLOCK;
    else
        flags |= O_NONBLOCK;
    return fcntl(fd, F_SETFL, flags) != -1;
}

I just noticed that if I shutdown netcat (or telnet) and start a new one, I can read again the first message sent. But that's it.


Solution

  • accept() accepts a new connection. So every time through the loop you set fd_client_serv to the socket id of a new connection, abandoning the old connection. ("Abandoning" in the sense that you will never read from it again, since you have lost its id. You haven't closed it but you've forgotten about it.)