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

mjc*_*jcs 1 c++ sockets multithreading

我刚刚开始用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);

    }
Run Code Online (Sandbox Code Playgroud)

我在这行编译时遇到错误:

std::thread th(Network::SocketHandler, (void*)csock);
Run Code Online (Sandbox Code Playgroud)

说:std :: thread :: thread(_Callable &&,_ Args && ...)[with _Callable = void(Network :: )(int); _Args = {void*}]没有已知的转换参数1从''到'void(Network :: &&)(int)'

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

Omn*_*ous 6

当你明白你真正想要的是什么时,你为什么要通过void *而不是?int *int *

只需将功能签名更改为:

void Network::SocketHandler(int* csock)
Run Code Online (Sandbox Code Playgroud)

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

std::thread th(Network::SocketHandler, csock);
Run Code Online (Sandbox Code Playgroud)

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

你应该做的是再次将功能签名更改为:

static void Network::SocketHandler(int* csock)
Run Code Online (Sandbox Code Playgroud)

然后你的代码就可以了.它看起来不像函数使用任何成员变量,因此它不需要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);

    }
Run Code Online (Sandbox Code Playgroud)

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

事实上,你的程序有内存泄漏.它从来没有收回它的空间mallocS对于csock指向.如果它运行了很长时间,它最终将耗尽内存,因为所有这些文件句柄的空间从未被回收.

您的程序可能还有文件句柄泄漏.你没有出现close在套接字中Network::SocketHandler.但由于我对整个程序没有可见性,我无法确定.

  • @ user1971401:我稍后会为你写点什么.实际上并没有那么大的变化.顺便说一句,他们是对的,C++ 11线程更好地用于各种原因. (2认同)