CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  网络编程

大家的接收线程是怎么实现的啊?怎么我的接收线程消耗CPU资源这么大啊?

楼主B2China(海陆空天电磁)2004-05-02 13:39:27 在 VC/MFC / 网络编程 提问

我的服务程序在一个客户端接入以后就开一个接收线程,负责接收它的数据。  
  在此期间客户机保持和服务器的连接。  
   
  实际运行时,发现这个接收线程一运行,CPU利用率达到100%,根本接收不了其他的连接,请问大家怎么处理接收线程的?怎么改善接收线程的性能?  
   
   
  //     接收数据线程如下:  
  DWORD   WINAPI   RecvThread(LPVOID   lParam)  
  {  
      int   Socket;  
      Socket=   (int   )lParam;  
      fd_set fdRead;  
      struct   timeval   tmvTimeout={0L,100L};  
      char   RecvBuf[256];  
     
      while   (TRUE)  
      {  
          //   初始化  
          FD_ZERO(&fdRead);  
          FD_SET(Socket,&fdRead);  
          int ret   =   select(0,&fdRead,NULL,NULL,&tmvTimeout);  
          if   (ret   ==   SOCKET_ERROR)  
          {  
                printf("Select()   Socket   error:   %d..\n",GetLastError   ());  
                continue;  
          }  
          else   if   (ret   >   0)  
                {      
                      if   (FD_ISSET(Socket,&fdRead))  
                        {     //   有数据可读  
                                nRecv=   recv   (Socket,   RecvBuf,   sizeof(   RecvBuf),   0);      
                                if   (nRecv   ==   SOCKET_ERROR)  
                                  {   //   读数据出错  
                                        printf("Recv   socket   error:   %d..\n",GetLastError());  
                                    }  
                                else    
                                  if   (nRecv   ==   0)  
                                  {   //   客户端断开连接  
                                              printf("remote   socket   closed..\n");  
                                              closesocket(Socket);    
                                              break;                                                                            
                                    }  
                                                                 
                                  //   数据读入成功,做数据处理  
                                  printf("Successfully   receive     %d   bytes..\n"),nRecv);    
                                  ProcessData(RecvBuf);    
                        }    
                }  
      }  
      printf("Recv   thread   exit   with   0..\n");  
      return   0;  
  }  
  问题点数:20、回复次数:10Top

1 楼B2China(海陆空天电磁)回复于 2004-05-02 13:40:52 得分 0

我是用whle(true),这个大循环来不停的监视客户端连接是否有数据可读的,可能是由于这个原因导致CPU利用率高的惊人。Top

2 楼xuweiqun(打雷啦)回复于 2004-05-02 14:20:31 得分 1

我在串口通信中使用的是事件的触发方式,所以只有数据来的时候,才触发接收,Top

3 楼elusion(落)回复于 2004-05-02 14:22:58 得分 1

sleep一下Top

4 楼wwwllg(野蛮人)回复于 2004-05-02 15:07:52 得分 5

一种方法是加sleep(1).在while里面。  
  另一个方法是,是用事件方式。  
   
  你的接收处理方法有问题  
  if   (ret   ==   SOCKET_ERROR)  
          {  
                printf("Select()   Socket   error:   %d..\n",GetLastError   ());  
                continue;//很显然,这里需要Getlastererro看看一下错误原因,这样,在不需要的时候,跳出循环。  
          }  
   
  Top

5 楼max_xy(夏平生)回复于 2004-05-02 18:55:50 得分 1

楼上的,请问怎么样处理select错误呢,按照您的意思。给点代码如何Top

6 楼max_xy(夏平生)回复于 2004-05-02 20:02:25 得分 0

我的线程加了SLEEP,cpu利用率大概20%.但是假如一个客户端需要联接很多个客户端,每个客户端对服务端的联接都使用一个线程的话,CPU的利用率就会很高。不知道能不能不用while而实现同样的功能。Top

7 楼truewq(aibieli)回复于 2004-05-02 20:22:09 得分 4

我也是用While实现的,不过我只是在监听网络,代码差不多你看一下嘛,刚开始我也是CPU占用很高,后来加了一个return   就好了:  
  DWORD   WINAPI   LoopScanThread(LPVOID   lpparam)  
  {  
  SOCKET   ListenSocket=(SOCKET)lpparam;  
   
  sockaddr_in   send;  
  int   sendlen=sizeof(send);  
  CString   aa2="----接收方最大允许连接数为10----";  
  AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)aa2.GetBuffer(0),1);  
  aa2.ReleaseBuffer();  
   
  //接收方允许最大的连结数是10  
  int   rc=listen(ListenSocket,10);  
   
  if(rc==SOCKET_ERROR)  
  {  
  CString   a5="----创建监听socket失败,请检查网络后重试----";  
  AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a5.GetBuffer(0),1);  
  a5.ReleaseBuffer();  
  ::MessageBeep(MB_ICONHAND);  
  return   0;  
  }  
   
  CString   aa3="----创建监听socket成功,开始监听网络----";  
  AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)aa3.GetBuffer(0),1);  
  aa3.ReleaseBuffer();  
  ::MessageBeep(MB_ICONASTERISK);  
  while(1)  
  {  
  SOCKET   ConnectSocket;  
   
  ConnectSocket=accept(ListenSocket,(sockaddr*)&send,&sendlen);  
   
  if(ConnectSocket==INVALID_SOCKET)  
  {  
  CString   a="----接收发送方请求失败----";  
  AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a.GetBuffer(0),1);  
  a.ReleaseBuffer();  
  ::MessageBeep(MB_ICONHAND);  
  return   -1;  
  }  
   
  CString   a="----接收请求成功,连接已经建立----";  
  AfxGetMainWnd()->SendMessageToDescendants(WM_LISTBOX,(WPARAM)a.GetBuffer(0),1);  
  a.ReleaseBuffer();  
  //直到accept()成切返回,然后进入别一个线程,来接收文件消息  
  DWORD   dwThread1;  
  ::CreateThread(NULL,0,GetFileInfoThread,(LPVOID)ConnectSocket,0,&dwThread1);  
  }  
  return   0;  
  }Top

8 楼max_xy(夏平生)回复于 2004-05-02 21:07:30 得分 1

刚刚觉得用SETTIMER來做,不用while循环。不知道cpu会不会降低一点。来做个测试。Top

9 楼wwwllg(野蛮人)回复于 2004-05-03 17:33:26 得分 5

BOOL   CClientOverlappedSock::OnRead()  
  {  
  if(!IsConnected())  
  return   false;  
  DWORD   dwTransbit   =   0;  
  DWORD   Resv   =   0;  
  DWORD   dwFlag   =   0;  
  WSABUF   buffer;  
  BOOL   bQuery   =   false;  
  int   state   =   0;  
   
  bQuery   =   WSAGetOverlappedResult(   m_RecSocket,   &ConnectedSocketOverlapped,  
  &dwTransbit,false,&dwFlag);  
  if(bQuery)  
  {  
  if(dwTransbit   ==   0)  
  {  
  OnClose();  
  return   true;  
  }  
  while(1)  
  {  
  if(   rPag.len   -   sizeof(PAG)   ==     DataRes)  
  {  
  ////  
  Work();  
  Reset();  
  ////  
   
  buffer.buf   =   (char*)&   rPag;  
  buffer.len   =   sizeof(PAG);  
  state   =   WSARecv(   m_RecSocket,&buffer,1,&Resv,  
  &dwFlag,   &ConnectedSocketOverlapped,NULL);  
   
  if(state   ==   0)  
  {  
  continue;  
  }else  
  {  
  DWORD   err   =   WSAGetLastError();  
  if(err   !=   WSA_IO_PENDING)  
  {  
  TRACE1("erro   code1   %d\n",err);  
  OnClose();  
  return   false;  
  }else  
  {  
  if(ERROR_IO_PENDING   ==   err)  
  {  
  return   true;  
  }  
  }  
  }  
  }else  
  if(   rPag.len   -   sizeof(PAG)   -     DataRes   >   0)  
  {  
  if(!m_bReadPending)  
  {  
  if(buff   ==   NULL)  
  {  
  buff   =   new   char   [   rPag.len   -   sizeof(PAG)];  
  memset(   buff,0,   rPag.len   -   sizeof(PAG));  
  buffer.buf   =     buff;  
  buffer.len   =   rPag.len   -   sizeof(PAG);    
  }  
   
  Resv   =   0;  
  buffer.len   =   rPag.len   -   sizeof(PAG)   -     DataRes;    
  buffer.buf   =     buff   +     DataRes;  
  state   =   WSARecv(   m_RecSocket,&buffer,1,&Resv,  
  &dwFlag,   &ConnectedSocketOverlapped,NULL);  
  if(state   ==   0)  
  {  
  DataRes+=Resv;  
  continue;  
  }else  
  {  
  DWORD   err   =   WSAGetLastError();  
  if(err   !=   WSA_IO_PENDING)  
  {  
  TRACE1("erro   code2   %d\n",err);  
  OnClose();  
  return   false;  
  }else  
  {  
  if(ERROR_IO_PENDING   ==   err)  
  {  
  m_bReadPending   =   true;  
  return   true;  
  }  
  }  
  }  
  }else  
  {  
  DataRes+=dwTransbit;  
  }  
  }  
  if(!IsConnected())  
  return   0;  
  Sleep(1);  
  TRACE1("RES   DATA   IS   %u\n",DataRes);  
  }  
  }else  
  {  
  DWORD   err   =   WSAGetLastError();  
  if(err   !=   ERROR_IO_INCOMPLETE)  
  {  
  OnClose();  
  TRACE1("erro   code3   %d\n",err);  
  return   false;  
  }else  
  return   true;  
  }  
  return   true;  
  }  
  吐血回贴!  
  当没有数据来时,根本不占用cpu.  
  Top

10 楼danscort2000(danscort.yu)回复于 2004-05-04 16:58:44 得分 2

加SLEEP(   )控制  
  或者用消息EVENT通知。  
  WHILE(   )  
  循环对CPU的消耗太巨大了,一定要有措施来主动交出CPU时间段Top

相关问题

  • 在线程中如何接收消息?
  • CSoecket::OnReceive 接收在主线程,有什么办法移到辅线程接收
  • 关于UdpClient.Receive()使用单线程还是多线程接收的效率问题!
  • 线程进入阻塞时,线程会不会让出CPU?
  • 串口接收线程"受扰"超时,影响接收数据的问题?
  • 再拿100,多线程数据接收中的错误.
  • 基于CWinThread的线程能接收消息吗?
  • 关于线程中接收事件消息的问题
  • 为什么线程接收不到PostThreadMessage发送的消息?
  • 如何监控线程CPU占有率?!

关键词

  • 线程
  • 数据
  • socket
  • 监听
  • cpu
  • 客户
  • 接收
  • rpag
  • datares
  • resv

得分解答快速导航

  • 帖主:B2China
  • xuweiqun
  • elusion
  • wwwllg
  • max_xy
  • truewq
  • max_xy
  • wwwllg
  • danscort2000

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo