在TCP和UDP协议的意义上,记录或数据边界是什么意思?

时间:2018-08-02 20:16:08

标签: sockets networking tcp

我正在学习套接字,并且在 SOCK_SEQPACKET 通信协议中找到了“数据或记录边界”一词?谁能用简单的词来解释什么是数据边界,以及 SOCK_SEQPACKET SOCK_STREAM SOCK_DGRAM 有何不同?

1 个答案:

答案 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'

(代码中通常还有其他与时序相关的方面会影响何时/是否实际发生。)