简体   繁体   English

套接字:当客户端读取消息时,多线程不起作用

[英]socket: multithreading doesn't work when client reads messages

I have a server, which can accept two socket connections. 我有一台服务器,可以接受两个套接字连接。 It creates a thread for each socket so that messages can be sent parallel. 它为每个套接字创建一个线程,以便可以并行发送消息。

Now I'm trying to code my client. 现在,我正在尝试编码我的客户端。

I create a class named SocketThread as a thread of socket. 我创建一个名为SocketThread的类作为套接字线程。 Here is the main code: 这是主要代码:

void SocketThread::ReadData()
{
    int n = 0;
    while (!finished)
    {
        while ((n = read(sockfd, recvBuff, sizeof(Data))) > 0)
        {
            std::cout<<std::this_thread::get_id()<<std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        }
    }
}

std::thread SocketThread::run()
{
    return std::thread([=] { ReadData(); });
}

in the function main : 在函数main

SocketThread s0("127.0.0.1", 10000);
SocketThread s1("127.0.0.1", 10000);
std::thread td0{sts[0].run()};
std::thread td1{sts[1].run()};
td0.join(); // stop here
td1.join();
// something else

When I execute the program, it will block at td0.join(); 当我执行程序时,它将在td0.join();td0.join(); , meaning that I can get the id of the thread td0 on the console and I can NEVER get the other thread. ,这意味着我可以在控制台上获取线程td0的ID,而从不获取其他线程。

However, when I remove (n = read(sockfd, recvBuff, sizeof(Data))) > 0 , which means that now the client is just a simple thread, that it won't receive anything, things gonna be fine ---- I can get two ids of the two threads. 但是,当我删除(n = read(sockfd, recvBuff, sizeof(Data))) > 0 ,这意味着现在客户端只是一个简单的线程,它不会接收任何东西,一切都会好起来- -我可以得到两个线程的两个ID。

Why? 为什么?

EDIT It seems that I used join incorrectly. 编辑看来我以前join不正确。
What I need is that main doesn't execute //something else until the two threads get 1000 characters together. 我需要的是main直到两个线程一起获得1000个字符后才执行//something else
What should I do? 我该怎么办?

You did not use join() incorrectly. 您没有错误地使用join() If you want main() to block until both threads end, your code is correct : td0.join() will block until thread td0 ends, and the same for td1 . 如果要让main()阻塞直到两个线程结束,则您的代码是正确的: td0.join()将阻塞直到线程td0结束,并且与td1相同。

Now, if you want your threads to end after receiving sizeof(Data) bytes, your function void SocketThread::ReadData() should rather look like this : 现在,如果您希望线程在接收到sizeof(Data)个字节后结束,则函数void SocketThread::ReadData()应该看起来像这样:

void SocketThread::ReadData()
{
    int n, total = 0;
    while (!finished)
    {
        while ((n = read(sockfd, &recvBuff[total], sizeof(Data) - total)) > 0)
        {
            total += n;
        }
        if (n == -1)
        {
            // manage error here
        }
        if (n == 0)
        {
            std::cout << "client shut the socket down; got " << total << " bytes over " << sizeof(Data) << std::endl;
            finished = true;
        }
    }
}

For a short explanation : there is no guarantee that you can get all data sent by client in a single read() operation, so you need to call read() and cumulate data into the buffer until you get a return value of 0 (meaning the client shut down the socket). 简短的说明:不能保证您可以通过一次read()操作获得客户端发送的所有数据,因此您需要调用read()并将数据累积到缓冲区中,直到返回值为0 (即客户端关闭套接字)。 read(sockfd, &recvBuff[total], sizeof(Data) - total) ensures that the incomming data is properly appended at the right position in the buffer. read(sockfd, &recvBuff[total], sizeof(Data) - total)确保传入的数据正确地附加在缓冲区的正确位置。

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

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