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

时间:2015-02-13 21:21:24

标签: c++ multithreading sockets object recv

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

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

然后我在客户端对象(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();
        }
    }

客户端类:

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;
        }

    }
}

2 个答案:

答案 0 :(得分:2)

分离后,Client对象看起来超出了范围。

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

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

答案 1 :(得分:1)

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

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

您肯定需要更仔细地检查accept,connect,read和write的返回值。此外,请确保您没有以非阻塞模式运行服务器的接受套接字。我不认为你是因为你没有看到任何输出,但如果你这样做它将无限循环错误产生大量线程,这些线程也会无限循环错误并可能使你的机器瘫痪。

如果我误解了正在发生的事情并且您确实获得了客户端连接并且“客户端连接”和“客户端方法问候!”输出,则很可能您对recv()的调用失败并且您是无视失败。所以,你处于一个紧密的无限循环中,尽可能快地反复输出“”。

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