2

我刚开始用 C++ 编码,我正在尝试构建一个多线程服务器,但我遇到了一些错误。首先,这是我得到的代码:

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::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Network:: )(int ); _Args = {void*}] 没有已知的参数 1 从 '' 到 'void (Network:: &&)(int )' 的转换</p>

我怎样才能解决这个问题?还是有更好的方法来创建多线程服务器任何其他帖子的示例?

4

1 回答 1

7

当很明显您真正想要的是a 时,为什么要传入 avoid *而不是a ?int *int *

只需将函数签名更改为:

void Network::SocketHandler(int* csock)

并删除执行调用的代码中的强制转换:

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

现在,您仍然会收到错误,而且原因不同。Network::SocketHandler是成员函数。它需要一个this指针。通常,您会使用类似object.SocketHandler(csock)or的语法调用此类函数objptr->SocketHandler(csock)。当您以这种方式调用它时,::std::thread您并没有给它一个要调用的对象。它没有this指针。

您应该做的是将函数签名再次更改为:

static void Network::SocketHandler(int* csock)

然后你的代码就可以正常工作了。它看起来不像函数使用任何成员变量,所以它不需要this指针。

另一方面,您似乎正在尝试调整最初为 pthread 编写的内容。如果我为 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空间csock。如果它运行了很长时间,它最终会耗尽内存,因为所有这些文件句柄的空间从未被回收。

您的程序也可能存在文件句柄泄漏。你没有出现closeNetwork::SocketHandler. 但由于我不了解您的整个计划,因此我无法确定这一点。

于 2013-01-18T18:20:51.490 回答