套接字:发送2Mb而不丢失数据

Sockets : send 2Mb without loss of data

本文关键字:数据 发送 2Mb 套接字      更新时间:2023-10-16

我在linux上使用套接字,我想在不丢失任何数据的情况下发送一个大表(超过2Mb),并且速度足够快,可以在客户端上获得流畅的视频。(我发送的是一个视频流)。

我试过两件事:

1°)一次发送整个表格

socketError = send(newsockfd,(char*) DataTab,sizeof(DataTab),0);
if (socketError < 0)
    error("ERROR server writing to socket");

2°)逐个发送元素

for (int i=0; i<nbelem; i++) // nbelem is greater than 600'000
{
    socketError = send(newsockfd,(char*) &DataTab[i],sizeof(&DataTab[i]),0);
    if (socketError < 0)
    error("ERROR server writing to socket");
}

一次发送表格很快,但我丢失了一些数据。

逐个发送元素效果良好,没有数据丢失,但速度太慢。

所以我有两个问题:可以在一个套接字中发送的数据(以字节为单位)的限制是什么?以及如何在不丢失数据的情况下快速发送表格?

PS:我的程序应该在本地或以太网中通信。没有设想互联网通信。

最简单的答案是:使用tcp套接字:socket(AF_INET, SOCK_STREAM, 0)

更复杂的答案是:如果你想使用udp,可以使用(或发明)一些带有传递检查、重传以及拥塞控制的协议。

通常,UDP是发送视频流数据的好主意,因为通常可以容忍丢失视频数据

如果您不能丢失数据,请考虑按照建议使用TCP!

可以通过UDP发送的最大数据包大小取决于网络中使用的硬件,没有固定的数字。如果你需要制作最好的数据包大小,你需要实现一种叫做"MTU Discovery"的东西。

如果你能猜得起的话,把数据包的大小定为1492。

编辑:

如果您使用的是Windows,请考虑放大接收器缓冲区大小:

int bufferSize = 64 * 1024;  // 64k
setsockopt( socket, SOL_SOCKET, SO_RCVBUF, (char *) & bufferSize );

网络编程很棘手,您可以考虑很多权衡。例如,如果您的服务器和客户端都在局域网或受控&可靠的广域网,您可以使用UDP。这样,您将节省TCP的开销,并且在大多数传输中不会丢失任何数据。

如果视频是通过互联网发送的,并且您需要可靠性,则必须使用TCP。如果您使用的是TCP,那么只需send()一次处理所有数据。TCP具有内置的可靠性和流量控制机制。在这种情况下,您无法加快数据传输。

您还可以考虑使用Raw套接字并实现自己的可靠性和流量控制。否则,处理好你的应用程序,即使有几个丢失的视频帧,它也会运行良好。

好吧,您没有回答是否使用UDP。如果您,那么这就是您的答案。UDP的最大数据报大小为64K。因此它不支持2MB的send()。因此,你必须做的第一件事(继续使用UDP)是将其分解为64K或更少的块。

然而,即便如此,这也是次优的。这是因为你的底层链路层可能不支持那么大的数据包。UDP通过将数据报拆分为数据包大小的传输来自动处理此问题。然而,UDP非常简单。如果这些数据包中的任何一个丢失或以某种方式被破坏,那么整个数据报必须被丢弃。另一方面,TCP只会重新发送丢失的数据包。如果你的UDP数据报只有两三个数据包,这可能不会很大。但是(假设标准数据大小为1420左右),所有的传输都需要33个独立的数据报(每个数据报有47个IP数据包)中没有任何问题。

既然你说你在一个私人网络上,这可能无关紧要。如果你可以控制网络流量,你可以通过在协议中确保在发送这些大数据包时没有其他人试图使用该网络来处理这一问题。如果流量不太大,一个好的快速智能交换机通常也能解决局域网上的此类问题。

这就是为什么许多人暗示,切换到TCP对你来说可能更容易。它在协议中处理所有这些。