客户端和服务器的 TCP 连接和不同的缓冲区大小
TCP connection and a different buffer size for a client and a server
如果我在客户端和服务器之间建立连接,并为它们各自配置不同的缓冲区大小,会发生什么情况。
这是我客户的代码:
import socket,sys
TCP_IP = sys.argv[1]
TCP_PORT = int(sys.argv[2])
BUFFER_SIZE = 1024
MESSAGE = "World! Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
服务器代码:
import socket,sys
TCP_IP = '0.0.0.0'
TCP_PORT = int(sys.argv[1])
BUFFER_SIZE = 5
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
while True:
conn, addr = s.accept()
print 'New connection from:', addr
while True:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received:", data
conn.send(data.upper())
conn.close()
这意味着我将被限制为只有 5 个字节?这意味着我将无法收到完整的数据包并且会丢失 1024-5 数据包?
我或者这是否意味着我只能获得 5 个字节的数据包,这意味着我必须将 1024 除以 5 并获得 204.8 个数据包(?),而不是在客户端发送时接收一个 1024 字节的数据包听起来不可能。
该代码中一般发生了什么?
谢谢。
你的论点是基于这样的假设,即单个 send
应该匹配单个 recv
。但这种情况并非如此。 TCP 是字节流,而不是基于消息的协议。这意味着重要的是传输的字节。对于读取 50 个字节是否需要一个或 10 个 recv
无关紧要。
除此之外,send
也不能保证发送完整的缓冲区。它可能只发送缓冲区的一部分,即发送方需要实际检查 return 代码以找出给定缓冲区中有多少现在实际发送以及需要重试以稍后发送多少。
请注意,底层的“数据包”又是另一回事了。如果有 2000 字节的 send
,通常需要发送多个数据包(取决于底层数据 link 层的最大传输单元)。但这并不意味着一个也需要多个recv
。如果所有 2000 字节都已传输到接收方的 OS 级别接收缓冲区,那么即使它们以多个数据包传输,也可以立即读取它们。
您的套接字不会丢失剩余的 1024 - 5 (1019) bytes.it 刚刚存储在套接字上并准备好再次读取!所以,你需要做的就是再次从套接字中读取。您要读取的缓冲区的大小由您自己决定。并且您不限于 5 个字节,您只是将每次读取的读取缓冲区限制为 5 个字节。因此,要读取 1024 个字节,您必须读取 204 次,再加上一次读取,这将是最后一次读取。但请记住,最后一次读取用 null 填充了最后一个缓冲区索引。这意味着现在没有更多字节可用。
如果我在客户端和服务器之间建立连接,并为它们各自配置不同的缓冲区大小,会发生什么情况。
这是我客户的代码:
import socket,sys
TCP_IP = sys.argv[1]
TCP_PORT = int(sys.argv[2])
BUFFER_SIZE = 1024
MESSAGE = "World! Hello, World!"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()
print "received data:", data
服务器代码:
import socket,sys
TCP_IP = '0.0.0.0'
TCP_PORT = int(sys.argv[1])
BUFFER_SIZE = 5
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
while True:
conn, addr = s.accept()
print 'New connection from:', addr
while True:
data = conn.recv(BUFFER_SIZE)
if not data: break
print "received:", data
conn.send(data.upper())
conn.close()
这意味着我将被限制为只有 5 个字节?这意味着我将无法收到完整的数据包并且会丢失 1024-5 数据包? 我或者这是否意味着我只能获得 5 个字节的数据包,这意味着我必须将 1024 除以 5 并获得 204.8 个数据包(?),而不是在客户端发送时接收一个 1024 字节的数据包听起来不可能。
该代码中一般发生了什么?
谢谢。
你的论点是基于这样的假设,即单个 send
应该匹配单个 recv
。但这种情况并非如此。 TCP 是字节流,而不是基于消息的协议。这意味着重要的是传输的字节。对于读取 50 个字节是否需要一个或 10 个 recv
无关紧要。
除此之外,send
也不能保证发送完整的缓冲区。它可能只发送缓冲区的一部分,即发送方需要实际检查 return 代码以找出给定缓冲区中有多少现在实际发送以及需要重试以稍后发送多少。
请注意,底层的“数据包”又是另一回事了。如果有 2000 字节的 send
,通常需要发送多个数据包(取决于底层数据 link 层的最大传输单元)。但这并不意味着一个也需要多个recv
。如果所有 2000 字节都已传输到接收方的 OS 级别接收缓冲区,那么即使它们以多个数据包传输,也可以立即读取它们。
您的套接字不会丢失剩余的 1024 - 5 (1019) bytes.it 刚刚存储在套接字上并准备好再次读取!所以,你需要做的就是再次从套接字中读取。您要读取的缓冲区的大小由您自己决定。并且您不限于 5 个字节,您只是将每次读取的读取缓冲区限制为 5 个字节。因此,要读取 1024 个字节,您必须读取 204 次,再加上一次读取,这将是最后一次读取。但请记住,最后一次读取用 null 填充了最后一个缓冲区索引。这意味着现在没有更多字节可用。