在网络编程中,流和数据报有什么区别?

套接字(流)和套接字(数据报)的区别是什么? 为什么要使用一个而不是另一个?

81125 次浏览

很久以前,我读过一个很好的类比来解释两者之间的区别。我不记得我是在哪里读到这篇文章的,所以很遗憾我不能把这个想法归功于作者,但是我还是在核心类比中加入了很多我自己的知识。所以我们开始吧:

流套接字就像一个电话呼叫——一方发出呼叫,另一方应答,你们互相打招呼(TCP 中的 SYN/ACK) ,然后交换信息。一旦您完成了操作,就要说再见了(TCP 中的 FIN/ACK)。如果一方没有听到再见,他们通常会呼叫另一方回来,因为这是一个意想不到的事件; 通常客户端将重新连接到服务器。有一个保证,即数据不会以与您发送的顺序不同的方式到达,并且有一个合理的保证,即数据不会被损坏。

数据报套接字就像在课堂上传递一个注释。考虑一下这种情况,你不是直接旁边的人,你正在传递纸条,纸条将旅行从一个人到另一个人。它可能无法到达目的地,并且在到达目的地时可能被修改。如果你把两张纸条传给同一个人,它们可能会按照你不想要的顺序到达,因为纸条通过教室的路线可能不一样,一个人传纸条的速度可能不如另一个人快,等等。

因此,当信息有序且完整时,使用流套接字非常重要。文件传输协议就是一个很好的例子。你不想下载一些文件,其内容随机洗牌和损坏!

当订单不如及时交付重要时(想想 VoIP 或游戏协议) ,当你不想要更高的流开销时(这就是为什么 DNS 主要是一个数据报协议,这样服务器可以非常快速地同时响应许多许多请求) ,或者当你不太关心数据是否到达目的地时,你会使用数据报套接字。

为了扩展 VoIP/游戏的情况,这样的协议包括它们自己的数据排序机制。但是,如果一个数据包损坏或丢失,您不希望等待流协议(通常是 TCP)发出重新发送请求——您需要快速恢复。TCP 可能需要花费几分钟的时间来恢复,对于实时协议,如游戏或 VoIP,甚至三秒钟都是不可接受的!使用像 UDP 这样的数据报协议允许软件通过忽略丢失的数据或比 TCP 更快地重新请求数据,从这样的事件中极快地恢复。

VoIP 是一个简单忽略丢失数据的好方法——一方只会听到一个短暂的间隔,类似于当用手机与信号不好的人通话时发生的情况。游戏协议通常比较复杂,但是所采取的行动通常是忽略丢失的数据(如果随后收到的数据取代丢失的数据) ,重新请求丢失的数据,或者请求一个完整的状态更新,以确保客户端的状态与服务器的同步。

电流插座:

  • 服务器和客户端之间的专用和端到端通道。
  • 使用 TCP 协议进行数据传输。
  • 可靠无损。
  • 以类似顺序发送/接收的数据。
  • 恢复丢失/错误数据的时间很长

数据报插座:

  • 服务器和客户端之间没有专用的端到端通道。
  • 使用 UDP 数据传输。
  • 不是100% 可靠,可能会丢失数据。
  • 发送/接收的订单数据可能不相同。
  • 不要关心或快速恢复丢失/错误的数据。

如果是网络编程,我认为从套接字开始将是一个良好的开端。
Socket = ip + port
有三种插座
流(TCP,保证订单和交付,无重复,数据没有长度或字符边界,面向连接,可靠,并发)
数据报(UDP,基于数据包,无连接,数据报大小限制,数据可能丢失或重复,订单无保证,不可靠)
原始(直接访问低层协议 IP,ICMP)
我没有看到任何关于传输协议类型的严格规则,关于哪个套接字必须使用什么传输协议和可靠性不应该被误解,因为在两端都是活动的情况下 UDP 是可实现的。
可靠性指的更像是交付的可靠性,因为使用 TCP 作为传输协议有序号检查,而 UDP 中不存在这种协议。最好使用网络协议分析器,比如 wiresharktcpdump 等,看看你的软件到底在做什么; 纸上的验证或合并理论与你的实际工作。