socket的recv函数如何检测消息结束

Bob*_*421 2 sockets

看看这个基本的Python小程序:

import socket

tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind(("", 10000))

tcpsock.listen(10)
(sock, (ip, port)) = tcpsock.accept()

s = sock.recv(1024)
print(s)
Run Code Online (Sandbox Code Playgroud)

第二个程序:

import socket
import time

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 10000))
time.sleep(1)
sock.sendall(b'hello world')
Run Code Online (Sandbox Code Playgroud)

第一个程序是套接字服务器。它通过套接字接收消息并将其显示在控制台上。第二个程序是连接到服务器并向其发送消息的客户端。

如您所见,服务器读取最大长度为 1024 字节的消息。我的客户端发送了几个字节。我的问题是:服务器如何知道消息在“d”字符之后结束?

多年来我一直在使用套接字,并且我总是实现一种分隔符机制,以便知道消息何时停止。但它似乎自动工作。我的问题是:如何?我知道 TCP 汽车片段消息。那么,如果 paquet 在我的消息中间被截断,会发生什么?它是由操作系统管理的吗?

谢谢

Ste*_*ich 6

服务器如何知道消息在“d”字符之后结束?

它不是。TCP中甚至没有消息的概念。recv只是返回现有的内容:如果没有可用数据,它会阻塞;如果有数据可用,则返回可以读取给定大小的内容。“数据可用”意味着套接字接收缓冲区中有数据,这些数据是由操作系统内核放入其中的。换句话说:recv在返回请求的字节数之前不会阻塞,但当套接字接收缓冲区中至少有一个字节时它就会返回。

例如,如果客户端执行两次操作sendsendall在不久之后执行一次操作,则单个recv操作可能会同时返回两个“消息”。这可以通过推迟recv(在其之前添加一些睡眠)轻松触发,以便保证两条“消息”都到达客户端。

  • Recv 只是返回缓冲区所能容纳的尽可能多的已接收数据。例如,如果您的套接字的 tcp 堆栈的传入数据缓冲区中有 11 个字节,并且您的缓冲区至少有 11 个字节长,则它返回 11 个字节。tcp 堆栈的传入数据缓冲区中存在的字节数将取决于调用 recv() 之前接收到的 tcp 数据包数量以及每个数据包包含的数据量 - 这将取决于网络的性能特征以及 TCP 用来最大化吞吐量以响应网络行为的(相当复杂的)算法。 (4认同)