• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1220
  • Last Modified:

Win32 Socket recv function consuming my cpu cycles

Hello Experts!

I have coded up a simple win32 C++ server to run on Windows that accepts multiple client connections and hands each connection off to a handling thread, that will process client commands synchronously.  The handler works fine, but after the first command is handled, the application starts consuming 99% of of my CPU time even though memory consumption is stable.

I believe my recv call is blocking and requiring the cpu to keep checking for data.

After looking around at similar questions, someone suggested using fd_sets and select() and to then use "read" instead of "recv" on the socket, but I can't figure out which "read" they're referring to.

I'm no longer waiting on recv, I'm now waiting on select() as the below code shows:
main code:
 
if ((clntSock = accept(listenSocket, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0){
	printf("Failed to accept scoket connection\n");
}
else {
	/* clntSock is connected to a client! */
	ULONG NonBlock = 1;
	if (ioctlsocket(clntSock, FIONBIO, &NonBlock) == SOCKET_ERROR)
	{
		printf("Winsock tutorial error: ioctlsocket() failed with error %d\n", WSAGetLastError());
        else {
                handle_client_socket();//not the actual method call, just a placeholder
        }
}
 
 
handle_client_socket() {
	fd_set fd_reader;
	FD_ZERO(&fd_reader);
	FD_SET(args->clientSocket, &fd_reader);
	
	while (1)
	{
		int retVal = select(0, &fd_reader, NULL, NULL, NULL);
		if (FD_ISSET(args->clientSocket, &fd_reader))
		{
			/* Receive again until end of transmission */
			while (totalRecvd < totalBytesToRecv) /* Haven't received a full command yet */
			{
				if ((bytesRecvd = recv(args->clientSocket, charBuffer, RCVBUFSIZE, 0)) < 0) {
					printf("recv() failed while receiving command(%d) with error %d\n", loopCnt, bytesRecvd);
					pthread_exit(NULL);
				}
				totalRecvd += bytesRecvd;
                                  /*continuation of functioning receiving code*/
                        }
                 }
         }
}

Open in new window

0
wdoutre
Asked:
wdoutre
  • 3
2 Solutions
 
jkrCommented:
You should change the line

if ((bytesRecvd = recv(args->clientSocket, charBuffer, RCVBUFSIZE, 0)) < 0) {


to

if ((bytesRecvd = recv(args->clientSocket, charBuffer, RCVBUFSIZE, 0)) <= 0) {

because otherwise, you'll enter an infinite loop that causes that 99% CPU load after the message has been received completely.
0
 
wdoutreAuthor Commented:
If I change the code to

if ((bytesRecvd = recv(args->clientSocket, charBuffer, RCVBUFSIZE, 0)) <= 0) {

then I exit the thread, so instead I've changed it to the code below.

When I run this now, I get a windows error of 10035, which according to this website: http://frontier.userland.com/stories/storyReader$173 is a TCP error meaning: WSAEWOULDBLOCK -- Resource temporarily unavailable.

I thought that by using FD_SET and FD_ISSET and calling

ioctlsocket(clntSock, FIONBIO, &NonBlock)

I was changing my socket to be non-blocking, but apparently I wasn't.
while (totalRecvd < totalBytesToRecv) /* Haven't received a full command yet */
{
	memset(charBuffer, 0, sizeof(charBuffer));
	/* Receive message from client */
	if ((bytesRecvd = recv(args->clientSocket, charBuffer, RCVBUFSIZE, 0)) < 0) {
		//printf("recv() failed while receiving command(%d) with error %d\n", loopCnt, bytesRecvd);
		DWORD winError = GetLastError();
		printf("recv() failed while receiving command(%d) with windows error: %d.\n", loopCnt, winError);
		perror("P Error:");
		pthread_exit(NULL);
	}
	else if (bytesRecvd ==0){
		break;
	}
        totalRecvd += bytesRecvd;
        /*continuation of functioning receiving code*/
}

Open in new window

0
 
TuebloCommented:
Hello wdoutre,

in your first code snippet you have a while loop that only exits the thread execution when data is fetched. I think you can solve this by either
- having a Sleep(1) at the end of the while block or
- providing the select function with a proper timeval structure having a value greater than 0.

Regards,
Tueblo
0
 
wdoutreAuthor Commented:
Thanks for your input, the problem actually was occurring in a totally different section of my code.  The changes you suggested are good changes though even though they weren't quite what I was looking for, so I figured I'd give you and the other helpful poster points for your effort.

Thanks!
0
 
wdoutreAuthor Commented:
The cpu cycle consumption was actually occurring on a worker thread that was doing some HTTP fetches using libcurl.  But thanks for the help.
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now