套接字未接收到完整的流

Socket not receiving the complete stream

本文关键字:套接字      更新时间:2023-10-16

我正在编写一个程序来发送,另一个程序通过套接字接收图像流。一般而言:

  • 在客户端:我得到图像并在客户端预先可视化。然后我通过一个插座发送了它。

  • 在服务器端:我等待图像,然后预可视化它。

以下是与套接字相关的代码片段:

编辑:

客户端

unsigned int bytes = 0;
for (int i = 0; i < imgSize; i += bytes) {
    if ((bytes = send(clientSocket->getSocketDescriptor(), (char*)inputImage.data + i, imgSize - i, 0)) == 0) {
        assert(false);
    }
    std::cout << "Sent: " << bytes << std::endl;
}
char notifyChar[1];
recv(clientSocket->getSocketDescriptor(), notifyChar , 1 , 0);

服务器端

unsigned int bytes = 0;
for (int i = 0; i < imgSize; i += bytes) {
    if ((bytes = recv(serverQuads.getSocketDescriptor(0), (char *)sockData + i, imgSize - i, 0)) == -1) {
        assert(false);
    }
    std::cout << " Received: " << bytes << std::endl;
}       
char notifyChar[1] = { '0' };
send(serverQuads.getSocketDescriptor(0),notifyChar , 1, 0);

图像大小为57600(imgSize是根据3个常量(WIDTHHEIGHTCHANNELS)计算的),并且send()返回该值。但是服务器只接收53504个字节,所以它返回到recv(),但什么也没发生。它不断地等待其他4096个字节。

我现在有点困惑。我看了很多帖子,但找不出问题。有人能帮我吗?

已解决:

该错误不在此代码段中。另一个线程正在从socketDescriptor中读取并等待4096个字节。所以,现在一切都好了。

您没有使用recv的返回值来查找接收到的字节数。TCP为您提供无边界的数据流。它不是基于消息的。

这意味着您可以在一次阅读通话中接收部分消息或多条消息。您的代码必须能够处理此问题。

recv()在windows和linux上的第三个参数是char[]缓冲区的大小,而不是接收到的大小。它的使用是为了防止分割错误。

我建议您使用以下

  • 当您从客户端发送数据包时,单个数据包传输之间会出现几秒钟的延迟(这仅用于调试)。然后在服务器端检查是否接收到单独的数据包。如果tcpdump已启用,请在客户端上运行以下命令:

    tcpdump-nnv-s0-ieth0 dst主机dsthostip和tcp

以及服务器上的以下命令

tcpdump -nnv -s0 -ieth0 src host srchostip and tcp

检查这些命令的输出,以确保发送和接收的数据包大小正确,如果不是,那么哪一方是罪魁祸首。

  • 检查套接字缓冲区的大小。套接字缓冲区有一个默认大小(我认为64KB是默认大小),如果数据到达得太快,套接字缓冲区可能会溢出,数据包可能会丢失,但如果使用TCP套接字,这种情况应该不太可能发生。您可以增加缓冲区的大小,并检查问题是否仍然存在。

  • 在服务器端运行netstat-s命令,检查IP和TCP标签下是否有数据包丢失或丢弃。希望这能有所帮助。