C / C ++接收全部挂起,本地服务器发送数据

问题描述

我很难弄清TCP客户端服务器应用程序中的错误。我面临的问题:在我的recv函数的do-while循环中,如果条件为bytes > 0,该函数将永远挂起。用bytes == NMAX代替,一切正常,除非NMAX等于1。一些注意事项:进行一次send-recv可以正常工作,但是尝试先进行send-recv然后recv-send会永远挂起。 NMAX认设置为4096的常量。首先运行服务器,然后运行客户端。 这是我的发送功能

ssize_t sendData(const std::string data,int fd)
{
    ssize_t total = data.length(),bytes,sent = 0;

    do
    {
        ssize_t chunk = total > NMAX ? NMAX : total;
        bytes = send(fd,data.c_str() + sent,chunk,0);

        if (bytes == -1)
        {
            throw std::system_error(errno,std::generic_category(),"Error sending data");
        }

        total -= bytes;
        sent += bytes;
    } while (total > 0);

    return sent;
}

这是我的recv函数

std::string recvData(int fd)
{
    ssize_t bytes;
    std::string buffer;

    do
    {
        std::vector<char> data(NMAX,0);
        bytes = recv(fd,&data[0],NMAX,"Error receiving data");
        }

        buffer.append(data.cbegin(),data.cend());
    } while (bytes > 0); // Replacing with bytes == NMAX partially fixes the issue,why?

    return buffer;
}

这是客户端的主要功能

std::cout << "Sent " << sendData(data) << " bytes\n";
std::cout << "Received: " << recvData() << "\n";

这是服务器的主要功能

std::cout << "Received: " << recvData(client) << "\n";
std::cout << "Sent " << sendData("Hello from the server side!",client) << " bytes\n";

解决方法

程序的问题是接收方不知道总共要接收多少个字节。因此,它将无休止地尝试读取更多字节。

它“挂起”的原因是您执行了阻塞的系统调用(recv),只有在收到至少1个字节以上时,该系统调用才会取消阻塞。但是,由于对等方不会发送更多数据,因此永远不会发生。

要解决此问题,您需要对数据采用适当的线格式,以指示所传输数据的大小或开始和结束的位置。常用的方法是以二进制形式为其长度加上前缀(例如32位无符号int,采用大字节序格式)。另一种方法是在数据中包含指示其结束的指示符(例如,HTTP中的\r\n\r\n换行符)。

顺便说一句:您的send函数在data.length() == 0的情况下并不理想。在这种情况下,您将以0个字节执行send系统调用-这是不必要的。