Sign in to follow this  

Sockets program question(cpu loading)

This topic is 4856 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys,im wondering why is this code making the cpu loading so much?anyone know how could I down the cpu loading?it uses almost 90% in all machines.Thanks!Code: int startupServerForListening(unsigned short port); void shutdownServer(int socket); HANDLE threadHandle; HANDLE mutexHandle; FD_SET masterSet; bool gQuitFlag = false; void acceptingThreadProcedure(int* serverSocket) { // copy my socket over to a local variable int mySocket = *serverSocket; // run forever for (;;) { // accept a client like normal unsigned int clientSocket = accept(mySocket, 0, 0); // make sure things are ok if (clientSocket == SOCKET_ERROR) { // just stop of we received any errors printf("Accept Failed!\n"); // signal to quit the application gQuitFlag = true; // and quit this thread return; } else { // lock the mutex WaitForSingleObject(mutexHandle, INFINITE); // add this socket to the master set using our FD_SET() macro FD_SET(clientSocket, &masterSet); // unlock the mutex ReleaseMutex(mutexHandle); // a quick message printf("----------------------\n"); printf("client on %d connected\n", clientSocket); } } } void main() { // Startup our network as usual. // the socket my server will use for listening int serverSocket; // startup my network utilities with my handy functions serverSocket = startupServerForListening(9001); // check for errors if (serverSocket == -1) { printf("Network Startup Failed!\nProgram Terminating\n"); return; } // create the mutex mutexHandle = CreateMutex(NULL, false, NULL); if (mutexHandle == NULL) { printf("Error creating mutex\n"); shutdownServer(serverSocket); return; } // create the thread int threadId; threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)acceptingThreadProcedure, &serverSocket, 0, (LPDWORD)&threadId); if (threadHandle == NULL) { printf("Could not start acceptance thread\n"); shutdownServer(serverSocket); return; } Sleep(100); FD_ZERO(&masterSet); // the main loop ... run forever for (;;) { if (gQuitFlag) { break; } WaitForSingleObject(mutexHandle, INFINITE); // make the polling set and copy everything from masterSet FD_SET pollingSet = masterSet; // unlock the mutex ReleaseMutex(mutexHandle); // check if our set is empty if (pollingSet.fd_count == 0) { continue; } // the wait time timeval waitTime; waitTime.tv_sec = 0; waitTime.tv_usec = 0; // and select(). select from the polling set using fd_count as the number of sockets. We do not have a // write set nor an errors set, so just pass NULL for them. int result = select(pollingSet.fd_count, &pollingSet, NULL, NULL, &waitTime); // check for no sockets with data if (result == 0) { // no sockets have data continue; } // check for errors if (result == SOCKET_ERROR) { printf("Error in select()\n"); continue; } // for every socket in my polling set for (unsigned int i = 0; i < pollingSet.fd_count; i++) { // We can access the socket list directly using the fd_array member of the FD_SET unsigned int clientSocket = pollingSet.fd_array[i]; // We will be using the same variable length data system that we implemented in tutorial #4. // So we need a few variables to facilitate the communication. // the number of bytes we received int nBytes; // a buffer to hold my data #define MAX_MESSAGE_SIZE 1000 char buffer[MAX_MESSAGE_SIZE]; // the size of the message that is being sent unsigned long messageSize; // receive the message size first nBytes = recv(clientSocket, (char*)&messageSize, sizeof(messageSize), 0); // check for errors if (nBytes == SOCKET_ERROR) { int error = WSAGetLastError(); // handle the dropped connection if (error == WSAECONNRESET) { // lock our mutex WaitForSingleObject(mutexHandle, INFINITE); // remove the socket from our master set FD_CLR(clientSocket, &masterSet); // unlock our mutex ReleaseMutex(mutexHandle); // close the socket on our side, so our computer cleans up properly closesocket(clientSocket); // a quick message printf("client on %d disconnected\n", clientSocket); // move on to the next client continue; } else { // we failed, but it wasn't an error we were expecting ... so kill the server printf("Recv Failed!\n"); gQuitFlag = true; break; } } if (nBytes == 0) { // lock our mutex WaitForSingleObject(mutexHandle, INFINITE); // remove the socket from our master set FD_CLR(clientSocket, &masterSet); // unlock our mutex ReleaseMutex(mutexHandle); // close the socket on our side, so our computer cleans up properly closesocket(clientSocket); // a quick message printf("client on %d has finished the connection\n", clientSocket); printf("----------------------------------------\n"); // move on to the next client continue; } // convert the message size to host ordering messageSize = ntohl(messageSize); // receive the reset of the message nBytes = recv(clientSocket, buffer, messageSize, 0); // check for error if (nBytes == SOCKET_ERROR) { printf("Recv Failed!\n"); gQuitFlag = true; break; } ofstream q("file.txt"); q<<buffer; } } // cleanup shutdownServer(serverSocket); printf("Press Enter to Exit ...\n"); getchar(); } // ----------------------------------------------------------------------------------- // startupServerForListening() - a function to startup winsock, and open a socket for listening int startupServerForListening(unsigned short port) { // an error code we will use to get more information about our errors int error; // the winsock data structure WSAData wsaData; // startup winsock if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) { printf("Could Not Start Up Winsock!\n"); return -1; } // create my socket int mySocket = socket(AF_INET, SOCK_STREAM, 0); // make sure nothing bad happened if (mySocket == SOCKET_ERROR) { printf("Error Opening Socket!\n"); return -1; } // the address structure struct sockaddr_in server; // fill the address structure with appropriate data server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = INADDR_ANY; // and now bind my socket if (bind(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { printf("Bind Failed!\n"); closesocket(mySocket); return -1; } // mark my socket for listening if (listen(mySocket, 5) == SOCKET_ERROR) { printf("Listen Failed!\n"); closesocket(mySocket); return -1; } printf("Server Started\n"); return mySocket; } // ----------------------------------------------------------------------------------- // shutdownServer() - a function to shutdown a socket and clean up winsock void shutdownServer(int socket) { // kill my thread and my handle WaitForSingleObject(threadHandle, INFINITE); CloseHandle(threadHandle); CloseHandle(mutexHandle); // close our socket closesocket(socket); // shut down winsock WSACleanup(); printf("Server Shutdown\n"); }

Share this post


Link to post
Share on other sites
I guess it should be the main loop,the code is:

for (;;) {

// accept a client like normal
unsigned int clientSocket = accept(mySocket, 0, 0);

// make sure things are ok
if (clientSocket == SOCKET_ERROR) {

// just stop of we received any errors
printf("Accept Failed!\n");

// signal to quit the application
gQuitFlag = true;

// and quit this thread
return;

} else {



// lock the mutex
WaitForSingleObject(mutexHandle, INFINITE);

// add this socket to the master set using our FD_SET() macro
FD_SET(clientSocket, &masterSet);

// unlock the mutex
ReleaseMutex(mutexHandle);

// a quick message
printf("----------------------\n");
printf("client on %d connected\n", clientSocket);
}
}

Or,it could be for this timer?(this is another loop)

timeval waitTime;
waitTime.tv_sec = 0;
waitTime.tv_usec = 0;

// and select(). select from the polling set using fd_count as the number of sockets. We do not have a
// write set nor an errors set, so just pass NULL for them.

int result = select(pollingSet.fd_count, &pollingSet, NULL, NULL, &waitTime)


the server and client works well without any error.Thanks!

[Edited by - cofruben on August 26, 2004 11:51:03 AM]

Share this post


Link to post
Share on other sites
It isn't the first loop, since accept() blocks until the connection is accepted, and is no time consuming.

I think it is your message-processing loop. You are polling the buffers to see if a message has arrived. I prefer to spawn a thread to attend each connection, but if you don't want, you can sleep when no message is your "polling set".

for (;;) {
if (gQuitFlag) {
break;
}
WaitForSingleObject(mutexHandle, INFINITE);
...

See, you want to sleep both when no message has arrived, and also when there are still no connections, so before getting the mutex, write Sleep(100) (I say this because you have a nasty 'continue' below, which causes the loop to restart if there are still no connections).

This is a very bad solution. I prefer blocking my app until the IO operation happens, so I use a thread for each connection (though for a heavily-loaded server this may not be the optimal solution, I don't know).

Overall, try to better structure your code. I'm sorry but I can't help more. Hope this helps in some way.

Share this post


Link to post
Share on other sites
i guess jjmontes is right, the

for (;;) {
...
}

will eat most of your cpu time.

some ideas i got when looking at your code:

1. you don't need a separate thread for accept(); you can use the above loop in main() to call that code.

2. if you get rid of the thread you can get rid of all the mutexes and synchronization stuff

3. the loop then goes like this:

int main()
{
// create server socket
int srv=create_serversocket();
// add server socket to the FD-set (for select())
FD_SET(&readfds, srv);

while (1) {
// call select()
int s=select(maxfd, &readfds, ...);

// walk through all sockets
for (i=0; i<maxfd; i++) {
// is it the server socket? then call accept()
if (i==srv) {
cli=do_accept(srv);
// add the new client socket to the FD-set
FD_SET(&readfds, cli);
}
// otherwise read from a client connection
else {
do_read(i);
}
}
}


sometimes less is more :)

Share this post


Link to post
Share on other sites
You might want to change your mutex for a critical section. Using a mutex imply a user space to kernel space transition which amount to about a thousand cpu cycle roundtrip (see Programming Server-Side Applications for Microsoft Windows 2000 for reference).

But be warned that critical section are tied to one process and thus can't be used to do inter-process synchronization (which doesn't apply to your case anyway since you seem to be in a single process).

Gizz

Share this post


Link to post
Share on other sites

This topic is 4856 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this