2013-01-18 47 views
1

即时通讯只是开始在c + +编码,我想构建一个多线程服务器,但我有一些错误。首先,这里是我得到的代码:c + +多线程服务器与std ::线程铸造变量

while(true){ 
     printf("waiting for a connection\n"); 
     csock = (int*)malloc(sizeof(int)); 

     if((*csock = accept(hsock, (sockaddr*)&sadr, &addr_size))!= -1) 
     { 
      printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr)); 
      //std::thread th(&Network::SocketHandler, NULL); 

      std::thread th(Network::SocketHandler, (void*)csock); 
      th.detach(); 
     } 
     else 
     { 
      fprintf(stderr, "Error accepting %d\n", errno); 
     } 
    } 

    } 


    void Network::SocketHandler(void* lp) 
    { 
     int *csock = (int*)lp; 

     char buffer[1024]; 
     int buffer_len = 1024; 
     int bytecount; 

     memset(buffer, 0, buffer_len); 
     if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){ 
      fprintf(stderr, "Error receiving data %d\n", errno); 

     } 
     printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 
     strcat(buffer, " SERVER ECHO"); 

     if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){ 
      fprintf(stderr, "Error sending data %d\n", errno); 

     } 

     printf("Sent bytes %d\n", bytecount); 

    } 

我在这行编译时得到一个错误:

std::thread th(Network::SocketHandler, (void*)csock); 

说: 的std ::螺纹::线程(_Callable & &,_args & & ...)[with _Callable = void(Network :: )(int); _args = {无效*}] 没有已知的转换用于从“参数1”到“空隙(网络:: & &)(INT)”

如何解决这个问题?还是有更好的方式来创建一个多线程服务器的任何示例可能是其他职位?

+0

你可能会考虑看看Boost.Asio的C++网络库 –

回答

5

为什么你在传递一个void *而不是int *当明确你真正想要的是int *

只要改变函数签名:

void Network::SocketHandler(int* csock) 

,并删除在不调用的代码的转换:

std::thread th(Network::SocketHandler, csock); 

现在,你仍然会得到一个错误,这将是原因不同。 Network::SocketHandler是一个成员函数。它需要一个this指针。通常你会用类似object.SocketHandler(csock)objptr->SocketHandler(csock)的语法来调用这样的函数。当你用::std::thread这样称呼时,你并没有给它一个被调用的对象。它没有this指针。

你应该做的是再次改变函数签名:

static void Network::SocketHandler(int* csock) 

,然后你的代码会工作得很好。它看起来不像该函数使用任何成员变量,所以它不需要指针this

在另一个笔记上,它看起来像你正在尝试改写原来为pthreads写的东西。如果我正在为C++ 11线程库做这件事,我会以一种非常不同的方式来做到这一点。

我看不到你的整个程序,所以我没有真正的重新设计它的奢侈。但是,从我所看到的,我会做这些调整:

while(true){ 
     printf("waiting for a connection\n"); 
     int csock = -1; 

     if((csock = accept(hsock, (sockaddr*)&sadr, &addr_size))!= -1) 
     { 
      printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr)); 
      //std::thread th(&Network::SocketHandler, NULL); 

      std::thread th(Network::SocketHandler, csock); 
      th.detach(); 
     } 
     else 
     { 
      fprintf(stderr, "Error accepting %d\n", errno); 
     } 
    } 

    } 


    void Network::SocketHandler(int csock) 
    { 
     char buffer[1024]; 
     int buffer_len = 1024; 
     int bytecount; 

     memset(buffer, 0, buffer_len); 
     if((bytecount = recv(csock, buffer, buffer_len, 0))== -1){ 
      fprintf(stderr, "Error receiving data %d\n", errno); 

     } 
     printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 
     strcat(buffer, " SERVER ECHO"); 

     if((bytecount = send(csock, buffer, strlen(buffer), 0))== -1){ 
      fprintf(stderr, "Error sending data %d\n", errno); 

     } 

     printf("Sent bytes %d\n", bytecount); 

    } 

的变化是相当微妙的。 C++ 11线程库允许您调用函数并提供它们的所有参数,并以线程安全的方式处理它。无需再通过void *,也不需要使用mallocnew为这些参数创建存储空间,只需将线程需要的参数直接传递给线程构造函数即可。

您的程序实际上存在内存泄漏。它永远不会回收空间malloc s为csock指向。如果它运行了很长时间,它将最终耗尽内存,因为所有这些文件句柄的空间都不会被回收。

您的程序也可能有文件句柄泄漏。您看不到close插座Network::SocketHandler。但由于我对整个项目没有看到,所以我无法确定。

+0

根据你的意见,哪种方式更好?这是最初为pthreads写的,但有些人告诉我,c + + 11线程更好。 – mjcs

+2

@ user1971401:稍后我会为你写点东西。这其实并没有那么大的改变。顺便说一句,他们是对的,C++ 11线程更适合各种原因使用。 – Omnifarious

+1

@ user1971401:在那里,我尽可能地改变了你的程序,我可以提供关于它的知识并解释我的推理。 – Omnifarious