Skip to main content
gamedev.net
🔒 Locked

select() not functioning in Windows?

Started by The Great Sephiroth 6 replies 700+ views
Original Post
The Great Sephiroth
The Great Sephiroth
OK, I picked up TCP/IP in about an hour a day ago. I have already written a very basic chat server which works great. However, the client I am now working on, wants to give me problems. If I use FD_SET() each loop to put my socket into the fd_set variable, it will read data from the socket whenever it is recieved, but if I only set it before the main loop, it will recieve the first message and nothing more! Here is a sample. int WINAPI WinMain(...) { int SocketFD; fd_set ReadSet; //Grab a socket, fill in fields, etc //Connect no problem FD_ZERO(&ReadSet); FD_SET(SocketFD, &ReadSet); while(!Done) { //Handle Windoze messages select(SocketFD + 1, &ReadSet, NULL, NULL, &TV); if(FD_ISSET(SocketFD, &ReadSet)) { if((numBytes = recv(SocketFD, MSGBuffer, sizeof(MSGBuffer), 0)) <= 0) { if(numBytes == 0) { MessageBox(MainWnd, "Lost connection to host.", "Error", MB_OK); shutdown(SocketFD, 2); WSACleanup(); return Message.wParam; } else { MessageBox(MainWnd, "Error in recieve.", "Error", MB_OK); shutdown(SocketFD, 2); WSACleanup(); return Message.wParam; } } AddLog(MainWnd); } } return Message.wParam; } Doing it this way only recieves one message and no more. Now if I put the FD_* macro calls into the main loop above the select() function, it tries to get a message at every loop, which KILLS my CPU (it can take up to 2min to redraw the screen on a P3/866!). What am I not doing right? The server application works fine with recv() and send(). -The Great Sephiroth
-The Great Sephiroth
Teknofreek
Teknofreek
Yeah. I believe each call to select clears out the fd_set, so you do have to initialize it each time.

Now, as for it tanking your frame-rate. I can''t imagine that using the FD macros can make that much, or almost any difference. You sure that the socket isn''t blocking on some call and that is giving you the large pauses?

-John
John
stodge
stodge
I would agree: select() doesn''t use much CPU time at all. Are you sure that your socket is non-blocking? I think the method of setting a socket to non-blocking is different under Windows than under say Linux/Unix.
---------------------http://www.stodge.net
The Great Sephiroth
The Great Sephiroth
Oh God if you can tell me how to set non-blocking I''d owe ya''! The "fcntl" header in Windows is for DOS functions, and the O_NONBLOCKING stuff isn''t even defined.

As for clearing the list, if each call to select clears it, but using FD_SET() makes it try to recv(), how do I make it recv() only if data is available?

-The Great Sephiroth
-The Great Sephiroth
CWizard
CWizard
You need to rebuild your sets before you call select() as it''s purpose is to tell you which sockets something is ready on. It does this by clearing the sets from those sockets that are idle. Therefor, after a select() on a socket which there was nothing to read from, that socket will be cleared from the read set.

Just put these lines inside your while loop:
FD_ZERO(&ReadSet);
FD_SET(SocketFD, &ReadSet);


and you will be alright.


stodge
stodge
Try this example code:

http://www.nexit.no/wsock.html

Look for ioctlsocket in void CMainFrame::StartBroadcastServer. I believe that this is what you want.
---------------------http://www.stodge.net
nohbdy
nohbdy

//to set nonblocking...
SOCKET mySock;
unsigned long blah = 1;

//Connect socket
...
//Set nonblocking
ioctlsocket(mySock, FIONBIO, &blah);


also note that once a socket is in non-blocking mode, you need to check whether any errors you get are WSAEWOULDBLOCK

also, select can block if you tell it to, but it doesn''t have to (by setting the timeout values to 0 and 0) and unless your network code is in its own thread then you should definitely set it up to not block...

If you want to know the truth though, unless you care about cross-platform, you should use overlapped I/O or asynchronous notification for sockets on Windows With overlapped i/o being the better of the two... Just something to move on to once you figure out this select() thing.. and if you have a Win2k or XP machine you can try out I/O Completion ports which are even better for performance
The Great Sephiroth
The Great Sephiroth
Sorry it took a while to reply, DSL was down for a week! Talk about nearly going insane...

Anyways I am coding my server application so it will compile on Linux/Unix and Windoze. Heck, the only differences thus far are that Windoze needs the winsock header included and those winsock startup and cleanup functions must be called. It is a MUD server that I am coding, and now that I am back online, I hope to have a very basic model online within the week.

-The Great Sephiroth
-The Great Sephiroth

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.