Advertisement

Select() problem

Started by September 20, 2005 10:22 AM
8 comments, last by Megahertz 19 years, 5 months ago
Im trying to write a server that will someday be turned into a MUD. As of now, im writing the part that handles incoming connections and am trying to learn how to use select(). So far i have it set up to where in my mind i believe it should run the while loop until someone tries to connect, then select will see the connection attempt, print a message to the server console window, and end the loop. But as of now it doesnt work like that at all, and i cant figure it out. Im guessing my use of select is wrong.

int init_socket(void);
void game_loop(int sock);
void shutdown(void);
fd_set fSet;
int servSock;

int main(void)
{
    //Initilize winsock and setup a socket to listen
    servSock = init_socket();
    
    //Pass the listening socket to the main gameloop
    game_loop(servSock);
    
    //Once gameloop has completed, its time to shutdown the server
    //shutdown();
    
}


int init_socket(void)
{
    WSADATA wsaData;
    WSAStartup( MAKEWORD(2,2), &wsaData );
    
    SOCKET servSocket;
    //Creating a socket
    servSocket = socket(AF_INET, SOCK_STREAM, 0 );
    
    sockaddr_in server;
    
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    server.sin_port = htons( 8000 );
    
    //Binding socket
    bind(servSocket, (struct sockaddr*) &server, sizeof(server));
    
    //Listen on a socket
    listen( servSocket, 5);
}
    
    
    
void game_loop(int sock)
{
     struct timeval tv;
     struct sockaddr_in clientsock;
     
     //copy of fSet
     fd_set cSet;
     
     FD_ZERO(&fSet);
     FD_SET(sock, &fSet);
     done = false;
     
     while(!done)
     {
     memcpy( &cSet, &fSet, sizeof(fd_set));
     //wait for connection
     if(select(FD_SETSIZE, &cSet, NULL, NULL, &tv) < 0)
     {
     continue;
     }
     else
     {
         printf("do we get here if we attempt to connect?");
         done = true;
     }
     
     
     
     
     
     }
    
}
What actually happens? Does it hang, or does it keep returning negative values?

The two things I see are:

You're not initializing tv, so the timeout is unspecified, possibly invalid.

You're only binding to loopback, so someone connecting from a remote site would not get to your machine. You should use INADDR_ANY to bind to all network adapters.
enum Bool { True, False, FileNotFound };
Advertisement
It is stuck in the if loop, with select always returning a negative value. In my mind, when i connect i should be getting the "do we get here" message, but i dont, nothing happens. As for the timeval struct, i was led to believe that if i declared the struct like so, it would set all memebers to NULL, so its basically setting &tv NULL, and will wait forever for a connection.
Hello Talith,

Decleared variables on the stack get what ever value was in the satck at that time, which could be complete garbage.
Since timeval is a C struct it won't have a consturtor that set it to all 0.
Do a memset on it if you want to wait until you get a connection, or pass a NULL for timeval in select. That should make it block untill it get a connection.

Lord Bart :)

[Edited by - Lord Bart on September 20, 2005 2:12:45 PM]
Thanks for the replys. I changed &tv to NULL, still getting same thing, hanging at the if loop. I added in a printf to display the actual interger select was returning and it was 1, which is strange since that should make the if statement true. Any ideas? Maybe i have to call accept or call somewhere before select will give me a real result?
Ah! figured out the problem, kinda. In init_socket i needed to add a return servSocket. Otherwise gameloop was never passed a socket. in the below code, the first printf never gets printed

if(int sel = select(FD_SETSIZE, &cSet, NULL, NULL, NULL) < 0)     {     printf("Select: %d ", sel);     continue;     }     else     {         printf("do we get here if we attempt to connect?   sl is %d ", sel);         getchar();         done = true;     }


Once i connect it will print the do we get here message, but never the first. Any ideas?
Advertisement
Hello Talith,

can't declear a int in the if.
if(int sel = select(FD_SETSIZE, &cSet, NULL, NULL, NULL) < 0)
need int outside if.
int sel;
if((sel = select(FD_SETSIZE, &cSet, NULL, NULL, NULL)) < 0)

Lord Bart :)
Strange, both versions appear to work, whether i have the int inside the if or not. Although still not getting the first message before someone connects.
Ok, finally got it. First i gave tv a time to wait of 3 seconds. Select was blocking with it set to NULL, then i changed select < 0 to <= 0 because select was returning 0 if no one connected.
You can declare an int in the first part of the for loop.

for (int i=0; i<50; i++)

is completely valid. Whether or not this is a C++ thing or part of the ANSI C standard I'm not sure, but on modern compilers it does work. (at least Visual C++ and gcc/g++).

In any event, glad you found your problem.

-=[ Megahertz ]=-
-=[Megahertz]=-

This topic is closed to new replies.

Advertisement