C ++中的多线程,从套接字接收消息

Multithreading in C++, receive message from socket

我学习了 Java 8 个月,但决定在业余时间学习一些 c++。

我目前正在使用 minGW 在 QT 中制作多线程服务器。我的问题是,当客户端连接时,我创建了一个客户端实例(它是一个 class)并在客户端 class 构造函数中传递套接字。

然后我在客户端对象 (startClient()) 中启动一个线程,该线程将等待消息,但它没有。顺便说一句,startClient 是我创建线程的方法。请参阅下面的代码。

然后会发生什么?是的,当我尝试向服务器发送消息时,只有错误,服务器不会打印出新客户端连接,并且由于某种原因我的计算机开始非常努力地工作。在我关闭服务器程序之前,qtcreator 变得非常慢。

我实际上想要实现的是一个派生线程的对象,但我听说在 C++ 中这样做并不是一个好主意。

服务器中的侦听器循环:

for (;;)
    {
        if ((sock_CONNECTION = accept(sock_LISTEN, (SOCKADDR*)&ADDRESS, &AddressSize)))
        {
            cout << "\nClient connected" << endl;

            Client client(sock_CONNECTION); // new object and pass the socket
            std::thread t1(&Client::startClient, client); //create thread of the method
            t1.detach();
        }
    }

客户class:

Client::Client(SOCKET socket)
{
    this->socket = socket;
    cout << "hello from clientconstructor ! " << endl;
}

void Client::startClient()
{
    cout << "hello from clientmethod ! " << endl;

    // WHEN I ADD THE CODE BELOW I DON'T GET ANY OUTPUT ON THE CONSOLE!
    // No messages gets received either.
    char RecvdData[100] = "";
    int ret;
    for(;;)
    {

        try
        {
            ret = recv(socket,RecvdData,sizeof(RecvdData),0);
            cout << RecvdData << endl;
        }
        catch (int e)
        {
            cout << "Error sending message to client" << endl;
        }

    }
}

您的 Client 对象在分离后似乎超出了范围。

if (/* ... */)
{
  Client client(sock_CONNECTION);
  std::thread t1(&Client::startClient, client);
  t1.detach();
} // GOING OUT OF SCOPE HERE

您需要创建客户端对象的指针并对其进行管理,或者将其定义在不会超出范围的更高级别。

您从未看到服务器的任何输出这一事实可能意味着您的客户端首先无法连接到您的服务器。检查您在连接呼叫中是否正确地进行了 IP 寻址。如果这看起来不错,那么可能有防火墙阻止了连接。关闭它或打开必要的端口。

您的连接客户端可能会从连接中收到错误,它正在将其解释为成功,然后尝试尽可能快地在无效套接字上发送大量流量,这就是您的机器似乎正在努力工作的原因。

您肯定需要更仔细地检查来自接受、连接、读取和写入的 return 值。另外,请确保您不是 运行 服务器的非阻塞模式接受套接字。我不认为你是因为你没有看到任何输出,但如果你看到它会无限循环错误产生大量线程,这些线程也会无限循环错误并可能使你的机器崩溃。

如果我误解了正在发生的事情,而你确实获得了客户端连接并有 "Client connected" 和 "hello from client method ! " 输出,那么很可能你对 recv() 的调用失败了,你正在忽略失败。所以,你处于一个尽可能快地重复输出 "" 的紧密无限循环中。

您可能还想将 catch 块更改为 catch (...) 而不是 int。我怀疑 recv() 或 cout 会抛出一个 int。即便如此,当 recv 失败时也不会调用该 catch 块,因为 recv 不会抛出任何异常 AFAIK。它 return 通过它的 return 值来指示它的失败。