Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FD_ISSET returns always false

I'm new in C sockets programming, and I'm trying to implement client-server non-blocking application, by using select(...).

When I run on debug the server code and try to connect the client, the select(...) returns 1 (as expected) but for some reason, the FD_ISSET doesn't find the file descriptor ID in the descriptors set.

I've already spend several days in debugging and I'm running out of ideas what could be the problem. Any help would be much appreciated!

void server_listen(int port_number){


    tcpsock_t * server, * client;
    fd_set master_set, working_set;
    int listen_sd;

    int max_sd, rc, desc_ready, bytes, result, close_conn;
    dplist_node_t * reference;




    if (tcp_passive_open(&server,PORT)!=TCP_NO_ERROR) exit(EXIT_FAILURE);
    if (tcp_get_sd(server,&listen_sd)!=TCP_NO_ERROR) exit(EXIT_FAILURE);

    FD_ZERO(&master_set);
    max_sd = listen_sd;
    FD_SET(listen_sd, &master_set);

    do {
        timeout.tv_sec  = 30;
        timeout.tv_usec = 0;

        memcpy(&working_set, &master_set, sizeof(master_set));
        printf("Waiting on select()...\n");
        rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);

        if (rc < 0)
        {
            perror("  select() failed");
            break;
        }
        if (rc == 0)
        {
            printf("  select() timed out.\n");

        }
        desc_ready = rc;
        for (int i=1; i <= max_sd  &&  desc_ready > 0; ++i)
        {
            if (FD_ISSET(i, &working_set))
            {
                desc_ready -= 1;

                if (i == listen_sd)
                {
                    printf("  Listening socket is readable\n");

                  //do something with the new socket
                }

            }
            else
            {
                printf("  Descriptor %d is readable\n", i);
                close_conn = FALSE;

               //read data from already existing socket connection

            } /* End of existing connection is readable */
        } /* End of if (FD_ISSET(i, &working_set)) */
    }
    while (end_server == FALSE);

}

int tcp_passive_open(tcpsock_t ** sock, int port)
{
    int result;
    struct sockaddr_in addr;

    tcpsock_t * s = (tcpsock_t *) malloc(sizeof(tcpsock_t));
    s->cookie = 0;  
    s->port = -1;
    s->ip_addr = NULL;
    s->sd = -1;

    s->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL);

    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = PROTOCOLFAMILY;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(port);
    result = bind(s->sd,(struct sockaddr *)&addr,sizeof(addr));
    result = listen(s->sd,MAX_PENDING);
    s->ip_addr = NULL; 
    s->port = port;
    s->cookie = MAGIC_COOKIE;
    *sock = s;
    return TCP_NO_ERROR;
}

int tcp_get_sd(tcpsock_t * socket, int * sd)
{
  *sd = socket->sd;
  return TCP_NO_ERROR;
}
like image 962
Ksenia Beloturkina Avatar asked Jun 12 '26 13:06

Ksenia Beloturkina


1 Answers

Your for loop starts at 1. If listen_sd comes back as 0, your loop will fail.

So, change:

for (int i=1; i <= max_sd  &&  desc_ready > 0; ++i)

Into:

for (int i=0; i <= max_sd  &&  desc_ready > 0; ++i)

Also, with just one file descriptor, you don't really need the for loop at all.


UPDATE:

Since you've posted your tcp_* functions, I can comment further. Because you did not show what PROTOCOLFAMILY, TYPE, and PROTOCOL are, they are suspect.

Since you're having trouble, check the return values from socket, bind, and listen for any error.

For an example of a simple working client/server application, see my answer here: executing commands via sockets with popen()

like image 156
Craig Estey Avatar answered Jun 15 '26 03:06

Craig Estey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!