gpt4 book ai didi

带有 std::thread 转换变量的 C++ 多线程服务器

转载 作者:行者123 更新时间:2023-11-30 00:54:21 24 4
gpt4 key购买 nike

我刚开始用 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 = {无效*}]参数 1 没有从“”到“void (Network::&&)(int)”的已知转换

我该如何解决这个问题?或者是否有更好的方法来创建多线程服务器,或者其他帖子的示例?

最佳答案

当很明显您真正想要的是 int * 时,为什么要传入 void * 而不是 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 为那些你可以的参数创建存储空间只需将线程需要的参数直接传递给线程构造函数即可。

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

您的程序也可能存在文件句柄泄漏。您似乎没有关闭 Network::SocketHandler 中的套接字。但由于我无法了解您的整个计划,因此我无法确定这一点。

关于带有 std::thread 转换变量的 C++ 多线程服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14404889/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com