我正在学习套接字,并且在 SOCK_SEQPACKET 通信协议中找到了“数据或记录边界”一词?谁能用简单的词来解释什么是数据边界,以及 SOCK_SEQPACKET 与 SOCK_STREAM 和 SOCK_DGRAM 有何不同?
答案 0 :(得分:1)
此答案https://stackoverflow.com/a/9563694/1076479很好地说明了消息边界(“记录边界”的另一个名称)。
将答案扩展到SOCK_SEQPACKET
:
SOCK_STREAM
提供了两个对等方之间数据的流的可靠,顺序的通信。它不维护消息(记录)边界,这意味着应用程序必须在提供的流之上管理自己的边界。
SOCK_DGRAM
提供了数据报的不可靠传输。数据报是独立的胶囊,其边界得以保留。这意味着,如果您在对等体A上发送20字节的缓冲区,则对等体B将收到20字节的消息。但是,它们可以被删除或乱序接收,这取决于应用程序来解决并处理。
SOCK_SEQPACKET
是一种尚未被广泛使用的较新技术,但是它试图兼顾上述两种优点。也就是说,它提供了可靠的顺序通信,该通信还以一个单元的形式传输整个“数据报”(并因此保持了消息边界)。
通过显示被忽略时发生的事情,最容易证明消息边界的概念。初学者经常在这里在SO上张贴这样的客户端代码(为了方便起见,使用python):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.4.122', 9000))
s.send(b'FOO') # Send string 1
s.send(b'BAR') # Send string 2
reply = s.recv(128) # Receive reply
和与此类似的服务器代码:
lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind(('', 9000))
lsock.listen(5)
csock, caddr = lsock.accept()
string1 = csock.recv(128) # Receive first string
string2 = csock.recv(128) # Receive second string <== XXXXXXX
csock.send(b'Got your messages') # Send reply
然后他们不明白为什么服务器在第二个recv
调用中挂起,而客户端在其自身的recv
调用中挂起。发生这种情况是因为客户端发送的(可能)两个字符串都捆绑在一起,并在服务器端的第一个recv
中作为一个单元接收。也就是说,两个逻辑消息之间的消息边界未被保留,因此string1
经常包含一起运行的两个块:'FOOBAR'
(代码中通常还有其他与时序相关的方面会影响何时/是否实际发生。)