Winsock多客户端和多线程,计算机很努力

时间:2014-02-02 09:13:07

标签: c++ multithreading sockets winsock

我正在尝试在c ++套接字编程中构建多客户端服务器,我在多线程中发现了一些麻烦。我使用_beginthread来创建一些线程。当我们想要构建多客户端服务器时,我认为我们应该有一个可以随时使用循环来处理套接字接受的线程,到目前为止它工作正常(对我没有麻烦)。

之后我做了一些线程来处理 Client-DataReceiver ,我认为它比我们创建1个线程来处理所有客户端更好地交替循环整个客户端。多线程会因为它们同步工作而做得更好,我认为。

当我完成所有操作时,服务器的工作速度很慢/很难,甚至使用到100%的CPU使用率? 也许我的代码中有一些缺失/错误的东西?

   void Initialize(){
      [....Server initialize goes here...]
       _beginthread( acceptNewClient, 0, (void*)1);  //the thread that handle accepter
    }
    SOCKET ClientSocket;
    void acceptNewClient(void* arg)
{
    while(true){
    ClientSocket = accept(ListenSocket,NULL,NULL);
    if (ClientSocket != INVALID_SOCKET) 
    {
        char value = 1;
        setsockopt( ClientSocket, IPPROTO_TCP, TCP_NODELAY, &value, sizeof( value ) );
        Client_Socket *client = new Client_Socket(ClientSocket); 
        _beginthread(ReceiveFromClient, 1,client );   //handle of client data receiver
        client_list.push_back(client);
    }
  }     
}
void ReceiveFromClient(void* client_sockets)
{
   Client_Socket * client_socket = (Client_Socket*)client_sockets;
   while(true){
       server->doReceive();    
   }
}

修改

在弄清楚这种情况后,我认为这个问题是线程本身 我甚至尝试过新的控制台项目:

#include <process.h>
    void tes(void * arg){
        while(true){

        }
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    _beginthread( tes, 0, (void*)1);
    while(true){}
        return 0;
    }

线程对于计算机来说太难了,我认为错误就是线程本身。 那些代码确实使CPU 100%CPU,我的线程代码或解决方案是否有问题解决这种情况?

3 个答案:

答案 0 :(得分:2)

正如我几个小时前暗示的那样,原因是你出于某种原因将套接字置于非阻塞模式,并且你没有使用select(),只是在recv()周围循环。它无论如何都没有意义,因为你每个连接使用一个线程。

根据你的回答,解决方案不是将套接字重新置于阻塞模式,而是首先删除设置非阻塞模式的代码,阻塞模式是默认的,正如@cHao指出的那样。

答案 1 :(得分:1)

100%CPU很可能是由while循环(while(true) server->doReceive();)引起的。使用套接字的正确方法是在套接字上等待,直到有一些有用的东西要做。启用此功能的标准C ++函数是select

更高级的方法是使用I / O完成端口,但在您的阶段,该技术太先进,甚至可能根本不需要。

答案 2 :(得分:-1)

我发现了问题。首先,如果您想在每个客户端使用线程构建服务器,首先必须注意的是:

  

确保您事先使用ioctlsocket

将SOCKET设置为阻止模式

这实际上非常有意义! 好吧,当我们创建这样的线程时:

unsigned __stdcall threadFunc(void * arg) 
{   
    while(1) {

    }
    return 0;
}

看起来如此简单的线程代码,但这是一个导致cpu工作如此困难的问题。 当recv winsocks的函数使用非阻塞模式调用时,它们将始终重复到while语句,当没有任何数据需要读取时,它们会像comp一样快速地旋转。当然这不是个好主意。 因此,如果我们想要克服它,当然正确的方法是:将套接字设置为非阻塞。

u_long iMode = 0;
iResult = ioctlsocket(ClientSocket, FIONBIO, &iMode);

当recv()被称为机器的Socket将等待,直到他们有一些字节要读。用这种方式'快速旋转'将不再发生

非常感谢..