2013-06-11 2 views
0

Мой код - односерверное/множественное клиентское приложение UDP с использованием WSAWaitforMultipleEvents().Использование процессора идет на 100% при запуске нескольких потоков

На стороне сервера есть 3 ReceiveThreads, и каждый получающий поток имеет свой собственный sendThread. Есть три Клиента. все это работает на одной машине.

Код ReceiveThread находится внутри Пока (1). Клиент также продолжает отправлять данные в течение (1) цикла.

Receive Thread только продолжает получать буфер и продолжает записывать буфер в текстовый файл.

Если получено EOF или EXIT, receivetread также должен завершиться и его SendThread.

Отправить тему с другой стороны только продолжает читать из другого текстового файла и продолжает отправлять данные, считанные из текстового файла через сокет.

Проблема, с которой я столкнулась, заключается в том, что использование ЦП превышает 100% при запуске этого кода.

Это связано с тем, что все три потока сервера работают в режиме While (1), и все клиенты также читают из текстового файла и отправляют данные по сокету в то время как (1)?

Я пытался выяснить причину использования этого 100% -ного использования ЦП с тех пор, пока он ничего не понял, кроме как (1).

EDIT:

код так долго, но я добавляю его, если кто-то хочет, чтобы увидеть его.

DWORD WINAPI sendAllThreadProcedure(LPVOID param) 
    { 
     threadDetailStruct* myDetailStruct = (threadDetailStruct*) (param); 
     int threadNumber,portNumber; 
     char *ipNumber; 
     SOCKADDR_IN sendSocket = myDetailStruct->cliSock; 
     SOCKET sendSocketIdentifier = myDetailStruct->cliSockIdentifier; 
     threadNumber = myDetailStruct->threadNum; 


     char clientPort[32],*clientIP = inet_ntoa(sendSocket.sin_addr); 
     int cliPort = ntohs(sendSocket.sin_port); 
     itoa(cliPort,clientPort,10); 
    //======================================================================= 
     int clientSocketLength = sizeof(SOCKADDR_IN); 
     char receiveBuffer[10000]; 
     int recv_len=0; 
    //======================================================================= 


     char file[32]="File.txt"; 
     int sendCount=0; 
     FILE *fpSend; 
     while(1) 
     { 
     if(WaitForSingleObject(terminate_thread_event[threadNumber],0) == WAIT_OBJECT_0) 
      { 
       ResetEvent(terminate_thread_event[threadNumber]); 
       break; 
      } 
     if((fpSend = fopen(TEXT(fileName), "r+b")) == NULL) 
     { 
      //"Unable to open the File" 
      continue; 
     } 
     else 
     { 
     char file_buffer[10000]; 
     int bytes_read=0; 
     char new_buffer[1000] = "FILE",send[1000]; 
     if(sendto(sendSocketIdentifier, new_buffer, sizeof(new_buffer), 0, (struct sockaddr *) &sendSocket, sizeof(sendSocket))<0) 
     { 
     //FILE MEssage NOT SENNT!" 
     continue; 
     } 
     else 
     { 
      while(fpSend!=NULL) 
      { 
      if(WaitForSingleObject(terminate_thread_event[threadNumber],0) == WAIT_OBJECT_0) 
      { 
      ResetEvent(terminate_thread_event[threadNumber]); 
       closesocket(sendSocketIdentifier); 
      fclose(fpSend); 
      return 0; 
      } 
      if((bytes_read=fread(file_buffer, sizeof(char), 5, fpSend))<=0) 
      { 
      if(feof(fpSend)) 
      { 
       char new_buffer[1000] = "EOF",send[1000],exit_message[12]; 
        if(sendto(sendSocketIdentifier, new_buffer, sizeof(new_buffer), 0, (struct sockaddr *) &sendSocket, sizeof(sendSocket))<0) 
       { 
        //"EOF NOT SENNT!" 
        break; 
       } 
        fclose(fpSend); 
        break; 
      } 
      else 
      { 
       /*Unable to copy file into buffer*/ 
        fclose(fpSend); 
       break; 
      } 
      } 
      else 
      { 
      if(sendto(sendSocketIdentifier, file_buffer, bytes_read, 0, (struct sockaddr *) &sendSocket, sizeof(sendSocket))<0) 
      { 
       //"Bytes read from File NOT SENT!" 
       fclose(fpSend); 
      break; 
      } 
      else 
      { 
       sendCount = sendCount+1; 
      } 
      } 
     } 
     } 
    Sleep(100); 
     closesocket(sendSocketIdentifier); 
     return 0; 
    } 

    // ==================== 
    // RECEIVE Thread 
    DWORD WINAPI newrecvThreadProcedure(LPVOID param) 
    { 
     newRecvThreadDetailStruct* myDetailStruct = (newRecvThreadDetailStruct*) (param); 
    char newDetail[256], threadNumber_char[12], ipNumber[32], 
    *detail = myDetailStruct>newsocketDetail; 
     int portNumber,threadNumber_int = myDetailStruct->threadNum; 
     sscanf(detail,"%s %d",ipNumber,&portNumber); 
     itoa(threadNumber_int,threadNumber_char,10); 

     strcpy(newDetail,threadNumber_char); 
     strcat(newDetail," "); 
     strcat(newDetail,detail); 
     struct node *cur, *newNode; 

     EnterCriticalSection(&cs); 
     cur =cread(); 
     cur->data = newDetail; 
     cur->n=NULL; 
     push(cur); 
     newNode = pop(); 
     MessageBox(NULL,"PUSH DONE!","PUSH!",MB_ICONEXCLAMATION | MB_OK); 
     if (ResetEvent(data_available_event) == 0) // signal sender thread that data is available 
      { 
       MessageBox(NULL,"RESET Event is not Set","Failed!",MB_ICONEXCLAMATION | MB_OK); 
      } 
     LeaveCriticalSection(&cs); 

     char file[64] = client.txt; 

     //==================================================================== 
     // Creating New Socket Now 
      WSADATA wsa; 

     //Initialise winsock// 
     if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) 
      { 
      char err[128]; 
      itoa(WSAGetLastError(),err,10); 
      MessageBox(NULL, 
         err, 
         "WinSock Initialization FAILED", 
         MB_ICONINFORMATION); 
      exit(EXIT_FAILURE); 
      } 

     //Create a socket// 
     SOCKET newSocketIdentifier; 
     SOCKADDR_IN newSocket; 
     if((newSocketIdentifier = socket(AF_INET , SOCK_DGRAM , 0)) == INVALID_SOCKET) 
      { 
      // "Socket Creation Failed", 
      exit(EXIT_FAILURE); 
      } 
     //Socket Created// 

     //Prepare the sockaddr_in structure// 
     newSocket.sin_family = AF_INET; 
     newSocket.sin_addr.s_addr = INADDR_ANY; 
     newSocket.sin_port = htons(portNumber); 

     //Bind// 
     if(bind(newSocketIdentifier ,(struct sockaddr *)&newSocket, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) 
      { 
         //"BIND FAILED inside Thread" 
      } 

     //Bind Done// 

     int waitRet; 
     WSAEVENT hEvent = WSACreateEvent(); 
     WSANETWORKEVENTS events; 
     WSAEventSelect(newSocketIdentifier, hEvent, FD_READ | FD_WRITE); 

     SOCKADDR_IN clientSocket; 
     int clientSocketLength = sizeof(SOCKADDR_IN); 
     char receiveBuffer[3000]={0}; 
     int recv_len = 0,receiveCount = 0; 

     while(1) 
      { 
      waitRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, INFINITE, FALSE); 
      //WSAResetEvent(hEvent); 
      if(WSAEnumNetworkEvents(newSocketIdentifier,hEvent,&events) == SOCKET_ERROR) 
       { 
          //"FAILURE" 

        continue; 
      } 
      else 
      { //else event occurred starts 
       if(events.lNetworkEvents & FD_READ) 
        { 
        if((recv_len = recvfrom(newSocketIdentifier, receiveBuffer, sizeof(receiveBuffer), 0, (struct sockaddr *) &clientSocket, &clientSocketLength)) == SOCKET_ERROR) 
          { 
           continue; 
          } 
         else 
          { 
           if(memcmp(receiveBuffer,"NewSocket",9) == 0) 
            { 
            if(sendto(newSocketIdentifier, "NewSocket ACK", sizeof("NewSocket ACK"), 0, (struct sockaddr *) &clientSocket, sizeof(clientSocket))<0) 
             { 
    //"NewSocket ACK not SENNT!",err,MB_ICONEXCLAMATION | MB_OK); 
              continue; 
           } 
          else 
           { 
             break; 
           } 
         } 
        } 
       } 
      } 
      } 
     threadDetailStruct threadDetail; 
     threadDetail.cliSock = clientSocket; 
     threadDetail.cliSockIdentifier = newSocketIdentifier; 
     threadDetail.threadNum = threadNumber_int; 
     AHN_glb_sendAllThreadHandle[threadNumber_int] = CreateThread(NULL, 
                   0, 
                   sendAllThreadProcedure, 
                   (LPVOID)&threadDetail, 
                   0, 
                   &idThread[threadNumber_int] 
                  ); 
     while(1) 
      { 
      waitRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, INFINITE, FALSE); 
      //WSAResetEvent(hEvent); 
      if(WSAEnumNetworkEvents(newSocketIdentifier,hEvent,&events) == SOCKET_ERROR) 
       { 
           // "FAILURE" 
        continue; 
      } 
      else 
      { //else event occurred starts 
       if(events.lNetworkEvents & FD_READ) 
       { //check for network event starts 
         //FD_READ 
         if((recv_len = recvfrom(newSocketIdentifier, receiveBuffer, sizeof(receiveBuffer), 0, (struct sockaddr *) &clientSocket, &clientSocketLength)) == SOCKET_ERROR) 
          { 
    //"after FD READ Could not Receive Data" 

           continue; 
         } 

        if(memcmp(receiveBuffer,"EXIT",4) == 0) 
         { 
            SetEvent(terminate_thread_event[threadNumber_int]); 
         } 
        if(memcmp(receiveBuffer,"FILE",4) == 0) 
         { 
         FILE *fprecv = fopen(TEXT(file),"wb"); 
         while(1) 
         { 
          waitRet = WSAWaitForMultipleEvents(1, &hEvent, FALSE, 0, FALSE); 
            if(WSAEnumNetworkEvents(newSocketIdentifier,hEvent,&events) == SOCKET_ERROR) 
          { 
               fclose(fprecv); 
               break; 
          } 
          else 
          { 
               if(events.lNetworkEvents & FD_READ)//else event occurred starts 
           { 
                if((recv_len = recvfrom(newSocketIdentifier, receiveBuffer, sizeof(receiveBuffer), 0, (struct sockaddr *) &clientSocket, &clientSocketLength)) == SOCKET_ERROR) 
                  {         MessageBox(NULL,"error","Data Reception Failed",MB_ICONINFORMATION); 
                  fclose(fprecv); 
                  exit(EXIT_FAILURE); 
                  break; 
              } 
                receiveCount = recv_len+receiveCount; 
             if(memcmp(receiveBuffer,"EXIT",4) == 0) 
             { 
             SetEvent(terminate_thread_event[threadNumber_int]); 
             fclose(fprecv); 
             return 0; 
             } 
                if(memcmp(receiveBuffer,"EOF",3) == 0) 
                 { 
                  fclose(fprecv); 
                  break; 
                 } 
                if(memcmp(receiveBuffer,"FILE",4) == 0) 
                 { 
                  fclose(fprecv); 
                  remove(TEXT(file)); 
                  fprecv = fopen(TEXT(file),"wb"); 
                  continue; 
                 } 
                **if(fwrite(receiveBuffer, 1, recv_len, fprecv)<0) 
                 { 
                  MessageBox(NULL,"problem while writing file","Error!",MB_ICONINFORMATION); 
                  fclose(fprecv); 
                  break; 
                 }** 
               } //if FD_READ 
              }// else network event receievd ENDS 
            }// While(1) for receiveing File Ends 
               FILE *fp1 ; 
               if((fp1 = fopen(TEXT(file), "rb")) == NULL) 
               { 
                MessageBox(NULL,"Unable to open the File","Error!",MB_ICONEXCLAMATION |MB_OK); 
                break; 
               } 
               char filecmp[1000]; 
               strcpy(filecmp,"Client"); 
               strcat(filecmp,threadNumber_char); 
               strcat(filecmp,"Original"); 
               strcat(filecmp,".txt"); 
               FILE *fp2 ; 
               if((fp2 = fopen(TEXT(filecmp), "rb")) == NULL) 
               { 
                MessageBox(NULL,"Unable to open the Original File","Error!",MB_ICONEXCLAMATION | MB_OK); 
                break; 
               } 
               int ch1 = getc(fp1) ; 
               int ch2 = getc(fp2) ; 
               while((ch1!=EOF) && (ch2!=EOF) && (ch1 == ch2)) 
               { 
                ch1 = getc(fp1); 
                ch2 = getc(fp2) ; 
               } 
               char display[3000]; 
               strcpy(display,file); 
               strcat(display," Received and "); 
               strcat(display,filecmp); 
               int idx=GetWindowTextLength(AHN_glb_resultWindowHandle); 
               SendMessage(AHN_glb_resultWindowHandle,EM_SETSEL,idx,idx); 
               SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)"\r\n"); 
               if (ch1 != ch2) 
               { 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)"\r\n"); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)" "); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)TEXT(display)); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)" are Not Identical"); 
               } 
               else if (ch1 == ch2) 
               { 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)"\r\n"); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)" "); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)TEXT(display)); 
                SendMessage(AHN_glb_resultWindowHandle,EM_REPLACESEL,0,(LPARAM)" are Identical"); 
               } 

    fclose (fp1); 
    fclose (fp2); 

           } //if memecmp == FILE ENDS 
        } //if FD_READ ENDS 
       }// else if event occurred ENDS 
     }//while(1) ENDS 
     return 0; 
    } 
    // =============================================================================================================== 
+0

Реальный вопрос: что делает ваш код, когда у него нет реальной работы? Если он вращается в вашем цикле while, тогда вы собираетесь пережевывать весь процессор. – hatchet

+0

Нам нужно увидеть фактический код, чтобы иметь возможность диагностировать проблему. Сверху моей головы: используете ли вы неблокирующие функции для отправки или получения данных? Если это так, вы можете заняться процессором тем, что по сути является оживленным ожиданием, когда потоки могут спать до прибытия данных. – idoby

ответ

2

Да, это из-за времени (1).

UDP по умолчанию является асинхронным, поэтому любой цикл while (1), проходящий через recv или отправляемый по udp, будет работать на полной скорости (он не дожидается появления сообщений в буфере). Если производительность не является вашей целью, добавьте

#include <time.h>  
usleep(1000); // 1000 microseconds is a millisecond 

, чтобы вы могли отложить некоторые циклы выполнения процессора.

На самом деле UDP следует использовать только в ситуациях, когда поток не успевает ждать ввода-вывода и имеет другие вычисления, которые он мог бы выполнять, или если один и тот же поток взаимодействует с пользователем, и задержка будет неприемлемой ,

+5

Хотя лучше, чем спиннинг, сон - не идеальный ответ. – hatchet

+8

Блокировка ввода-вывода существует именно по этой причине. – idoby

+1

Я полностью согласен с вами обоими. UDP следует использовать только в ситуациях, когда поток не успевает ждать ввода-вывода и имеет другие вычисления, которые он мог бы выполнять. Редактирование ответа. – Triclops200

Смежные вопросы