Advertisement

Winsock 2 Pausing on Recv()

Started by September 20, 2006 10:40 PM
13 comments, last by hplus0603 18 years, 5 months ago
Hi all, I currently have a working client/server system, where multiple clients can connect to the server. The server basically loops through a vector containing all the client sockets and on each one does a recv(). However the recv() seems to wait to actually get data before it continues running through the code. // Clear message theMessage = ""; // Receive data from the socket while(recv(p->theSocket, &ch, 1, 0)) { if (ch == '\n') { break; } theMessage += ch; } So if one client hasn't sent a message, recv() on the server will wait until it does get a message before continuing. Does anyone have a good workaround for this issue?
Thanks for the post.

I'm having trouble figuring out how to use WSARecv. Currently my receive code is as follows:

// Receive data from the socket
while(recv(p->theSocket, &ch, 1, 0))
{
if (ch == '\n')
{
break;
}
theMessage += ch;
}

How do I translate this to use WSARecv?

Thanks for any help!
Advertisement
u_long Arg = 1;ioctlsocket(MySocket,FIONBIO,&Arg);


to enable non-blocking mode for a socket.
-- Rasmus Neckelmann
Setting it to non-blocking seems to be causing strange behaviour.

On my server I have:

DWORD cThread::ThreadProc(){	// Status message	pMutex->MutexOn();	cout<<"Listen thread active..."<<endl<<endl<<"STARTING"<<endl;	pMutex->MutexOff();	// Loop forever listening for clients	while(1) {		// Wait for a client		SOCKET theClient;		theClient = accept(listenSocket, NULL, NULL);		// Turn on mutext to protect		pMutex->MutexOn();u_long Arg = 1;ioctlsocket(theClient,FIONBIO,&Arg);		// Create new record of connection		playerCon p;		p.theSocket = theClient;		p.lastPing = time(NULL);		p.sessionStart = time(NULL);		p.lastPingOK = true;				// Add player to vertex		pPlayers->push_back(p);		// Status report and turn off mutex		cout<<"Accepted client #"<<pPlayers->size()<<endl;		pMutex->MutexOff();	}  return 0;}


And my client has:

// Create connection to serverSOCKET connectToServer(){	WORD sockVersion;	WSADATA wsaData;	// Set version of winsock to use	sockVersion = MAKEWORD(2, 2);	// Initialize winsock	WSAStartup(sockVersion, &wsaData);	// Store information about the server	LPHOSTENT hostEntry;	/*	// USE THIS IF USING SERVER IP	in_addr iaHost;	iaHost.s_addr = inet_addr(SERVER_ADDRESS.c_str());	hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);	*/	// Get host my name (or domain name)	hostEntry = gethostbyname("localhost");	// Create the socket	SOCKET theSocket;	theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);u_long Arg = 1;ioctlsocket(theSocket,FIONBIO,&Arg);//int value = 0;//setsockopt(theSocket, SOL_SOCKET, SO_SNDBUF, (const char*)&value, sizeof(int));	// Fill a SOCKADDR_IN struct with address information	SOCKADDR_IN serverInfo;	serverInfo.sin_family = AF_INET;	serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);	// Set port to use	serverInfo.sin_port = htons(SERVER_PORT);	// Connect to the server	connect(theSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));	// Return socket for closing later	return theSocket;}


However it doesn't seem to work, it runs really really slowly.
Quote:
Original post by Anonymous Poster
Alternatively you can use select(), which is cross-platform and IMO a bit easier to get working properly than full asynchronous sockets.

James


No, no, no! select() is hazardous for servers since it causes Windows based servers to only support 64 simoultaneous connections, which is something you don't want in most normal, up to date and otherwise well written servers.
_______________________Afr0Games
Quote:
Original post by Afr0m@n
Quote:
Original post by Anonymous Poster
Alternatively you can use select(), which is cross-platform and IMO a bit easier to get working properly than full asynchronous sockets.

James


No, no, no! select() is hazardous for servers since it causes Windows based servers to only support 64 simoultaneous connections, which is something you don't want in most normal, up to date and otherwise well written servers.


Can't you just redefine FD_SETSIZE to a higher number?
Advertisement
Possibly, but there's a reason why select() on Windows has a default socket limitation of 64 sockets...

Anyhow, I think there's a solution to this problem discussed in this forum's FAQ.
_______________________Afr0Games
Usually nonblocking performs bad, because you have to poll, which requires some overhead.

On Unix you can use the poll api: http://www.hmug.org/man/2/poll.php. It is similar to select, but does not have the limitations. Though its a bit slower. The name is a bit irritating - it works just like select, and blocks until one of the sockets changes its state.

On windows you can use I/O completion ports: http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/
I suppose you could try forking the process.
Insufficent Information: we need more infromationhttp://staff.samods.org/aiursrage2k/
Quote:
No, no, no! select() is hazardous for servers since it causes Windows based servers to only support 64 simoultaneous connections, which is something you don't want in most normal, up to date and otherwise well written servers.


Yes, that is probably why most of the game servers are running on Linux. That is what we are planning to for our Battle.net remake :P

Linus has a much bigger limitation on the Select()

This topic is closed to new replies.

Advertisement