socket 接收线程实现(帖子)

来源:互联网 发布:多特vs希腊数据 编辑:程序博客网 时间:2024/05/16 18:09

我的服务程序在一个客户端接入以后就开一个接收线程,负责接收它的数据。  
  在此期间客户机保持和服务器的连接。  
   
  实际运行时,发现这个接收线程一运行,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;  
  }  
 


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

    发表者:elusion

    sleep一下

    发表者:wwwllg

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

    发表者:max_xy

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

    发表者:truewq

    我也是用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;  
      }

    发表者:max_xy

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

    发表者:wwwllg

    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.  
     

    发表者:danscort2000

    加sleep控制  
      或者用消息event通知。  
      while  
      循环对cpu的消耗太巨大了,一定要有措施来主动交出cpu时间段

http://blog.csdn.net/metasearch/article/details/2148228


原创粉丝点击