views:

424

answers:

2

Hey all, I have a server and a client running on two different machines where the client send()s but the server doesn't seem to receive the message. The server employs select() to monitor sockets for any incoming connections/messages. I can see that when the server accepts a new connection, it updates the fd_set array but always returns 0 despite the client send() messages. The connection is TCP and the machines are separated by like one router so dropping packets are highly unlikely.

I have a feeling that it's not select() but perhaps send()/sendto() from client that may be the problem but I'm not sure how to go about localizing the problem area.

    while(1)
{
    readset = info->read_set;   
    ready = select(info->max_fd+1, &readset, NULL, NULL, &timeout);

}

above is the server side code where the server has a thread that runs select() indefinitely.

rv = connect(sockfd, (struct sockaddr *) &server_address, sizeof(server_address));
printf("rv = %i\n", rv);
if (rv < 0)
{
    printf("MAIN: ERROR connect() %i:  %s\n", errno, strerror(errno));
    exit(1);
}
else
    printf("connected\n");

sleep(3);

char * somemsg = "is this working yet?\0";
rv = send(sockfd, somemsg, sizeof(somemsg), NULL);
if (rv < 0)
    printf("MAIN: ERROR send() %i:  %s\n", errno, strerror(errno));
printf("MAIN: rv is %i\n", rv);
rv = sendto(sockfd, somemsg, sizeof(somemsg), NULL, &server_address, sizeof(server_address));
if (rv < 0)
    printf("MAIN: ERROR sendto() %i:  %s\n", errno, strerror(errno));
printf("MAIN: rv is %i\n", rv);

and this is the client side where it connects and sends messages and returns

connected
MAIN: rv is 4
MAIN: rv is 4

any comments or insightful insights are appreciated.

A: 
connected
MAIN: rv is 4
MAIN: rv is 4

Odd that "rv is 4", especially considering the message was 22 chars long. "4" also tends to be the size of pointers in most 32 bit environments... I'd take a look at what sizeof(somemsg) gives you -- my guess is it's giving you the size of the pointer (4), not of the string (22).

Where are you updating the read set? The implementation details of the fd_set structure/type are not part of the BSD sockets interface, that i know of. It could be a pointer to somewhere, for all you know, and the system could be removing your client's socket from the original set the first time it wasn't "ready", and it'd never be checked again. The only way of updating a fd_set safely and portably is to to use the FD_* macros.

BTW, you don't need the trailing "\0" at the end of the string. C adds that to string literals for you.

cHao
Thanks for the \0 tip, I wasn't too sure. And yea I used FD_* macros to update `fd_set`s. It turns out that I wasn't initializing properly when I was setting it up from the memory block the thread shares.
Fantastic Fourier
What i mean is, saying "this_fd_set = another_fd_set;" is potentially unsafe. If the platform you're on implements fd_set's using pointers for some reason (which it's allowed to do!), some (possibly all) data will be shared between the two sets. And updating one could mess up the other.
cHao
A: 

There was something wrong with fd_set readset, rather than what I had thought was problematic. PROPS to qrdl for bringing it to my attention.

Fantastic Fourier