繁体   English   中英

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

[英]c++ multithreaded server with std::thread casting variables

我刚刚开始用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 )'的已知转换

我怎样才能解决这个问题? 还是有更好的方法来创建多线程服务器?

当您清楚您真正想要的是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为那些参数创建存储空间,您只需将线程需要的参数直接传递给线程构造函数即可。

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

您的程序也可能存在文件句柄泄漏。 您似乎没有close Network::SocketHandler的套接字。 但是由于我对您的整个程序不了解,因此我不确定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM