我有一个简单的服务器-客户机程序:
Inserver.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协议是"基于流"的。我在这里读到recv
阻塞IO,直到我的1000字节的请求得到满足。这似乎被服务器发出的send
或客户端发出的recv
打断了。以下3个字节未接收。
这些假设正确吗?如果不是,这到底是怎么回事?
提前感谢您的帮助!
我在这里读到recv阻塞IO,直到我的1000字节请求被满足。
这是错误的。recv
阻塞直到至少一个接收字节。给出的数字仅指定最大值应该读取的字节数,即既不是确切的数,也不是最小的数。
以下3个字节未接收。
在这个特定的情况下,很可能一次接收1000字节,留下3字节未读。但如果发送的数据量较大,特别是在MTU较低的链路上(即本地网络、WiFi与本地主机流量),情况就不同了。这里可以看到,在单个recv
期间,只有部分预期数据被接收。
即使假设send
将发送所有send
最多只能发送给定的数据。需要实际检查返回值,看看实际发送了多少。使用sendall
代替,如果你想让所有的发送。
我可以说socket.send()"刷新"/"重置"TCP流在这里吗?
。send
和recv
仅在套接字写缓冲区和读缓冲区上工作。它们实际上不会引起发送或接收。这是由操作系统来完成的。send
只是将数据放入套接字写缓冲区,操作系统最终将传输该数据。不过,这种传播并非在所有情况下都是立即完成的。如果有未确认的数据,发送可能会被延迟,直到数据被确认(具体取决于TCP窗口)。如果只有很少的数据在缓冲区中,操作系统可能会等待一段时间,让应用程序调用send
与更多的数据,以保持低传输开销(NAGLE算法)。
因此短语"flush"在这里没有真正的意义。和";reset"实际上意味着与TCP完全不同的东西——即使用RST标志强制断开连接。所以不要在这种情况下使用这些短语。