【问题标题】:When does OS flush the socket?操作系统何时刷新套接字?
【发布时间】:2015-06-26 06:56:20
【问题描述】:

假设我有这个 Python 代码:

read=true;
i=0;
while (read){
    data =sock.recv(100);
    i+=1;
    print data;
}

现在我在另一端输入 101 个字符的套接字。在接收结束时i 的值将是 2,因为所有提要都不会在 100 个字符的缓冲区中结束 - 一个剩余的字符将进入另一个迭代。这是可以理解的:缓冲区填满,信息被刷新到变量data。 但是如果我只给套接字提供 10 个字符会发生什么?缓冲区没有填满,那么sock 到底是如何知道在收到 10 个字符后将不再有流来的,是时候刷新缓冲区并将消息返回给“数据”了?

实际复制粘贴示例:

服务器:

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind("/tmp/somesfile")
s.accept(1)
s.listen()
conn, addr = s.accept()

i=0
read=True

while read:
    conn.recv(10)
    i = i + 1
    print i

客户:

c = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
c.connect("/tmp/somesfile")

发送数据(客户端上的控制台)

>>> c.send("aaaaa")
5
>>> c.send("a")
1
>>> c.send("a")
1
>>> c.send("a")
1
>>> c.send("a")
1
>>>

接收数据(服务器上的控制台)

'aaaaa'
1
'a'
2
'a'
3
'a'
4
'a'
5

服务器为接收到的数据准备了 10 字节的缓冲区。在第一次突发时,它收到 5 个字符 - 所有 5 个字符都存储到同一个缓冲区并被刷新。在进一步的 4 次突发中,服务器以接收之间的时间间隔一一发送 4 个分片。所有这些字符都以相同的模式刷新,即一个接一个。在任何情况下,缓冲区都没有填满。我的问题是:除了溢出之外,是什么导致服务器套接字刷新缓冲区?现在下一个字节不来怎么办?

字符串是以空字符结尾的字节模式。套接字流是否已终止?

【问题讨论】:

  • 我不确定你在问什么。 recv 的工作方式,你得到缓冲区中的任何东西,直到你要求的数量(这意味着:可能少于你要求的)。因此,如果只有 10 个字节,您将获得 10 个字节。操作系统必须处理的特殊问题是什么?
  • 如果你要 10 个字节但只有 5 个?它会阻塞流程,直到有人再提供 5 个字节并填充缓冲区?我可能被 python 宠坏了..那里的一切都过于简单了....
  • 我不记得它在 C 中是如何的,但是在 Python 中,如果我 recv(100) 并将套接字以 100 个字节一个接一个地馈送到另一端(比如之间有 1 秒的延迟) feeds)该过程将解锁 100 次。如果我一次给它 100 个字节 - recv() 只会解除阻塞一次。这意味着即使缓冲区未满,recv() 也会释放块。基本上我只是在不同的部分发送相同的数据,并且过程行为不同
  • 这与 Python 或 C 无关,而是与底层的套接字 API 相关。只要接收缓冲区中至少有 1 个字节,recv 就会返回这个而不是阻塞。

标签: sockets


【解决方案1】:

在接收结束时 i 的值为 2

没有。它可以是从 2 到 101 的任何值。recv 读取至少一个字节,最多读取远程端发送的字节。它可以读取介于两者之间的任何数量。

那么这只袜子到底是怎么知道在收到 10 个字符后将不再有流来的

它没有。它为您提供了那里的东西。

【讨论】:

  • 我已经修改了我的问题,并举例说明了我的问题。为什么它可以是任何东西 [2;101]?如果我使用相同的流发送数据,为什么 >2?我知道 recv() 至少读取一个字节,但是它为什么不会一个接一个地返回字节,并且足够聪明,可以知道流何时结束并返回缓冲区中的任何内容,尽管它没有满?触发点是什么?
  • 再次,它不知道流何时结束。它会在数据进入时为您提供数据。TCP 没有消息。用于发送数据的块大小对接收的块大小没有保证的影响。在实践中,某些行为非常普遍,但这并不值得依赖。
  • 通过以超过 200 毫秒的间隔连续两次执行 c.send("a") 来尝试此操作。您可能会在一次 recv 呼叫中收到“aa”。这是在玩闹。
  • 那么...它是时间相关的吗?假设我是 recv(2048),然后通过 MTU=1500 的网络将 2048 个字节作为单个消息发送。 recv() 收到 1500 个字节,然后突然网络出现故障,之后剩余的字节已发送。由于网络数据包之间的时间差异,服务器是否会将所有消息作为 2 条不同的消息接收?
  • 你没有明白我在说什么。您无法确保以某些块的形式接收数据流。你明白吗?您是否出于好奇而询问在实践中大部分时间会发生什么?
猜你喜欢
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
相关资源
最近更新 更多