Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么我的TCP/IP套接字每次读取接收的数据量不一致?_Python_Sockets_Tcp_Tcpclient - Fatal编程技术网

Python 为什么我的TCP/IP套接字每次读取接收的数据量不一致?

Python 为什么我的TCP/IP套接字每次读取接收的数据量不一致?,python,sockets,tcp,tcpclient,Python,Sockets,Tcp,Tcpclient,我正在从事一个使用Socket TCP/IP(服务器C#和客户端Python)的项目。 有时,视频流过后,Recv套接字的数据被分割。 我的数据为buff=22000字节,如果将其拆分为: buff = 1460 我不知道为什么,我研究了一些MTU、碎片、窗口大小等方法,但没有结果 特别是,如果我设置了StocketOpt,进程将显示得更少 self.sk.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1048576) --有关数据被拆分的

我正在从事一个使用Socket TCP/IP(服务器C#和客户端Python)的项目。 有时,视频流过后,Recv套接字的数据被分割。 我的数据为buff=22000字节,如果将其拆分为:

buff = 1460
我不知道为什么,我研究了一些MTU、碎片、窗口大小等方法,但没有结果 特别是,如果我设置了StocketOpt,进程将显示得更少

self.sk.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1048576) 
--有关数据被拆分的图像

这是我的Recv插座。

buff = self.sk.recv(1048576)
print("BUFF RECEIVE  :::  ::::: ---->>>>>      ",len(buff))
if buff == b'' :
  self.sk=None
  buff = None
  return buff
建议:这只发生在Chrome浏览器上(这意味着,如果数据丢失,则无法流式传输视频)。但在Firefox上,情况并非如此。如果数据丢失,它似乎会闪烁片刻,但之后可以继续流式传输。
-Chrome和FireFox这正是TCP的工作方式。它是一个没有内置消息帧的流协议,因此它可以自由地将字节以其选择的任何数量放入数据包中-它所保证的是,当接收套接字读取()字节时,字节仍将保持正确的顺序

因此,如果您的程序需要一定数量的字节才能继续,则由您的程序执行必要的缓冲以将这些字节组合在一起


至于为什么TCP可能会像您观察到的那样运行—它可能会对网络条件(丢弃的数据包、来自接收主机TCP堆栈的反馈等)做出反应,并尝试在当前环境下尽可能提高传输效率。传输数据的方式完全取决于TCP堆栈,不同的TCP堆栈可能会有不同的行为,只要它们遵循TCP规范的规则就可以了。

过了很长时间,我找到了问题的答案

**1/**当您使用send(Write)将包从服务器发送到客户端时。在客户端,接收有时无法获取完整数据。这并不意味着服务器上的发送/写入没有发送足够的数据。因为这是TCP/IP协议,所以接收不是渐变的,并且包在客户端(您的代码)将是碎片

**2/**您可以通过在发送/写入服务器端添加更多模式来解决此问题。例如,send(data)->send(Pattern+data),在客户端,您可以使用patern检查数据

**3/**此方法的局限性,包碎片化后,它可以“组合在一起”或有时不能。例如,您的发送数据=4000,在客户端,您的接收=1460+2540。
这就是我对我的问题的理解。

我不知道你的标题与你的问题的主体有什么关系。我甚至不明白你的头衔是什么意思。但您看到的是完全正常的-在您的用户空间代码中,您永远不应该将TCP视为一个数据包序列,而应该仅将其视为一个字节流。由操作系统将字节流拆分为数据包,并将其合并回接收方的字节流。发件人中的
send
不需要与收件人中的单个
recv
完全匹配。TCP不像UDP那样是一种数据报协议,而是一种字节流。感谢您快速响应。关于我的问题,当我从服务器获取数据时,我将使用该数据在Web上进行流式传输。但有时,数据被分割为1,2,3段,我不知道数据是否正确。例如:buff=22000字节时,它将流式传输正常(Web上的视频)但是如果buff被拆分,那么网络就不能传输视频。错误的是你的代码,而不是网络。关于每次接收的字节数的任何假设都是错误的。唯一的保证是您将接收到至少一个字节,或者遇到流结束或错误。你的头衔仍然是个谜。请修复它。您是否正试图接收1048576字节?如果是这样,只需继续调用
recv
函数(输入您仍然需要的字节数),直到收到那么多字节为止。如果你不知道你要读多少字节,那么你就沉没了。如果你不知道你想要什么,你没有办法要求它,必须改变你的设计。@vanloctc你说的是什么错误?谢谢你的回答。正如你所知,一个流将有22xxx数据,但正如你所看到的,有两个流,2920+19671和1460+21143,它似乎是MTU大小。我可以理解包被拆分或丢弃,所以我认为应该有“同步”来连接两个数据。TCP不需要按照你认为应该的方式运行;它只需要以符合TCP规范的方式运行。更多的建议是,这种情况只发生在Chrome上(这意味着,当数据丢失时不能流式传输视频),而不是在FireFox上。@vanloctc数据没有丢失。如果需要更多数据,只需再次调用read函数。如果你有理由认为数据应该连接起来,那么你的工作就是将数据重新连接起来。@DavidSchwartz,我改为(),但这不好。一周前你就被告知了这一切。它没有“终于”或“我找到了”。这个词不是“包”,而是“包”。i@user207421,如果我的愚蠢影响了你,我真的很抱歉。如果你有关于这个问题的链接,请给我,我可以从你那里学到更多。链接?这里有五个答案和十几条评论,它们都告诉你同样的事情。你需要的是一个支持你预期行为的链接。
buff = self.sk.recv(1048576)
print("BUFF RECEIVE  :::  ::::: ---->>>>>      ",len(buff))
if buff == b'' :
  self.sk=None
  buff = None
  return buff