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;
}
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With