我可以说 socket.send() "flushed"/"resets" 这里的 TCP 流吗?
Can I say that socket.send() "flushed"/"resets" the TCP stream here?
我有一个简单的服务器-客户端程序:
在server.py
中:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("127.0.0.1", 1234))
server_socket.listen()
connection_socket, address = server_socket.accept()
with connection_socket:
data = connection_socket.recv(1000)
connection_socket.send(bytearray([0x0]))
print(data)
server_socket.close()
在client.py
中:
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("127.0.0.1", 1234))
client_socket.send(bytearray([0x0, 0x1, 0x2]))
print(client_socket.recv(1))
client_socket.send(bytearray([0x3, 0x4, 0x5]))
client_socket.close()
这是我认为正在发生的事情:
我所知道的 TCP 协议是“基于流”的。我读过 here recv
阻塞 IO,直到我的 1000 字节请求得到满足。这似乎被服务器发出的 send
或客户端发出的 recv
打断了。未收到以下 3 个字节。
这些假设是否正确?如果不是,这里到底发生了什么?
在此先感谢您的帮助!
I've read here that recv blocks IO until my request of 1000 bytes has been fulfilled.
这是错误的。 recv
阻塞,直到收到 至少一个 字节。给定的数字只是指定了应该读取的最大字节数,即既不是确切数字也不是最小数字。
The following 3 bytes go unreceived.
在这种特定情况下,很可能一次收到了 1000 个字节,剩下 3 个字节未读。如果发送大量数据,尤其是通过具有低 MTU 的链接(即本地网络、WiFi 与本地主机流量),则情况有所不同。在这里可以看出,在单个 recv
.
期间仅接收到部分预期数据
即使 send
将发送 all 给定数据的假设也是错误的:send
最多只会发送 [=36] =] 给定的数据。需要实际检查 return 值以查看实际发送了多少。如果您想发送所有内容,请改用 sendall
。
Can I say that socket.send() “flushed”/“resets” the TCP stream here?
没有。 send
和 recv
仅在套接字写入和读取缓冲区上工作。它们实际上不会导致发送或接收。这是由 OS 代替完成的。 send
只是将数据放入套接字写入缓冲区,OS 最终将传输此数据。但是,这种传输并非在所有情况下都立即完成。如果有未完成的未确认数据,发送可能会延迟,直到数据被确认(细节取决于 TCP window)。如果缓冲区中只有少量数据,OS 可能会等待应用程序使用更多数据调用 send
以保持较低的传输开销(NAGLE 算法)。
因此“flush”这个词在这里没有实际意义。而“重置”实际上意味着与 TCP 完全不同的东西——即使用 RST 标志强行断开连接。所以不要在这种情况下使用这些短语。
我有一个简单的服务器-客户端程序:
在server.py
中:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("127.0.0.1", 1234))
server_socket.listen()
connection_socket, address = server_socket.accept()
with connection_socket:
data = connection_socket.recv(1000)
connection_socket.send(bytearray([0x0]))
print(data)
server_socket.close()
在client.py
中:
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("127.0.0.1", 1234))
client_socket.send(bytearray([0x0, 0x1, 0x2]))
print(client_socket.recv(1))
client_socket.send(bytearray([0x3, 0x4, 0x5]))
client_socket.close()
这是我认为正在发生的事情:
我所知道的 TCP 协议是“基于流”的。我读过 here recv
阻塞 IO,直到我的 1000 字节请求得到满足。这似乎被服务器发出的 send
或客户端发出的 recv
打断了。未收到以下 3 个字节。
这些假设是否正确?如果不是,这里到底发生了什么?
在此先感谢您的帮助!
I've read here that recv blocks IO until my request of 1000 bytes has been fulfilled.
这是错误的。 recv
阻塞,直到收到 至少一个 字节。给定的数字只是指定了应该读取的最大字节数,即既不是确切数字也不是最小数字。
The following 3 bytes go unreceived.
在这种特定情况下,很可能一次收到了 1000 个字节,剩下 3 个字节未读。如果发送大量数据,尤其是通过具有低 MTU 的链接(即本地网络、WiFi 与本地主机流量),则情况有所不同。在这里可以看出,在单个 recv
.
即使 send
将发送 all 给定数据的假设也是错误的:send
最多只会发送 [=36] =] 给定的数据。需要实际检查 return 值以查看实际发送了多少。如果您想发送所有内容,请改用 sendall
。
Can I say that socket.send() “flushed”/“resets” the TCP stream here?
没有。 send
和 recv
仅在套接字写入和读取缓冲区上工作。它们实际上不会导致发送或接收。这是由 OS 代替完成的。 send
只是将数据放入套接字写入缓冲区,OS 最终将传输此数据。但是,这种传输并非在所有情况下都立即完成。如果有未完成的未确认数据,发送可能会延迟,直到数据被确认(细节取决于 TCP window)。如果缓冲区中只有少量数据,OS 可能会等待应用程序使用更多数据调用 send
以保持较低的传输开销(NAGLE 算法)。
因此“flush”这个词在这里没有实际意义。而“重置”实际上意味着与 TCP 完全不同的东西——即使用 RST 标志强行断开连接。所以不要在这种情况下使用这些短语。