套接字(流)与套接字(数据报)有什么区别?为什么要使用一个而不是另一个?
3 回答
很久以前,我读了一个很好的类比来解释两者之间的区别。我不记得我在哪里读到的,所以不幸的是我不能把这个想法归功于作者,但无论如何我也在核心类比中添加了很多我自己的知识。所以这里是:
流套接字就像一个电话呼叫——一方拨打电话,另一方接听,你们互相问好(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 中不存在。最好使用网络协议分析器(如wireshark tcpdump 等)来查看您的软件到底在做什么;一种验证或将论文上的理论与您的实际工作相结合。