关于 TCP 和 UDP 传输数据产生的疑问?

个人背景:对网络传输刚刚有一定概念

在浏览器访问网页的过程中,tcp 和 ip 传输协议下,我们需要进行三次握手。

了解到三次握手的本质也是发送了数据包到对方电脑image.png

问题1:既然我三次握手也是发包,那我为什么不干脆一开始就直接发数据包呢?(省去三次握手,直接发不是更快吗?)

问题2:TCP 实际上干了什么才导致“三次握手以后的发包,和不进行握手直接发包”有了区别?

(不需要解释底层原理,希望可以举个简单的例子,让我有一点点相关概念)XD

阅读 2.4k
avatarAI BotBETA

问题1回答:

既然三次握手也是发包,为什么不干脆一开始就直接发数据包呢?原因如下:

三次握手的主要目的是确保通信双方能够建立起一个可靠的连接,并对后续的数据传输进行同步和协商。如果不进行三次握手而直接发送数据包,可能会出现以下问题:

  1. 无法确认对方是否在线或准备好接收数据:没有握手过程,发送方无法确认接收方是否在线或是否已经准备好接收数据。如果接收方不在线或未准备好,数据包可能会丢失或无法被正确处理。
  2. 数据同步问题:没有握手过程,发送方和接收方之间无法对数据的发送和接收进行同步。这可能导致数据包的乱序、重复或丢失,从而影响数据的完整性和准确性。
  3. 连接状态不明确:没有三次握手,通信双方无法明确连接的状态(如是否建立成功、是否断开等)。这可能导致数据传输的不确定性和不可靠性。

因此,虽然三次握手会增加一些额外的开销和延迟,但它确保了数据传输的可靠性和稳定性,避免了直接发送数据包可能带来的问题。

问题2回答:

TCP通过以下方式导致“三次握手以后的发包,和不进行握手直接发包”有了区别:

  1. 确认连接状态:通过三次握手,TCP能够确认通信双方已成功建立连接,并且都准备好进行数据传输。这确保了数据可以在一个稳定、可靠的通道上进行传输。
  2. 数据同步与顺序:TCP使用序列号对发送的数据包进行标记,确保接收方能够按照正确的顺序接收并处理这些数据包。这避免了数据的乱序和重复问题。
  3. 流量控制:TCP通过滑动窗口机制进行流量控制,确保发送方不会发送过多的数据导致接收方缓冲区溢出。这有助于避免网络拥塞和数据丢失。
  4. 错误检测与重传:TCP使用校验和来检测数据包在传输过程中是否发生错误,并在必要时请求重传丢失或损坏的数据包。这确保了数据的完整性和准确性。

因此,与不进行握手直接发包相比,经过三次握手后的TCP发包具有更高的可靠性和稳定性。虽然这可能会增加一些额外的开销和延迟,但对于需要可靠传输的应用场景来说,这些开销和延迟是值得的。

7 个回答
✓ 已被采纳
了解到三次握手的本质也是发送了数据包到对方电脑

本质?发送数据包到到对方电脑?

TCP provides a reliable bytestream, connection-oriented transport service on top of the unreliable connectionless network service provided by IP

TCP需要提供可靠的数据传输,但是它在协议栈中是位于提供不可以靠数据传输的IP协议之上,要做到这一点,需要在TCP层上做一些额外的事情来实现这一点。

什么是可靠的数据传输?

  • 正确传输
  • 按序传输
  • 不多发也不少发

怎么实现上面这一几点呢?

正确传输

  • 如何知道发错了?

    • check sum
  • 知道发错了怎么办?

    • 让对方重传

      • 重发哪一个报文呢?(或者说怎么标识每个报文?)

按序传输

  • 发送方给数据包报按顺序标号,应该先收到1号,然后再收到2号....,如果先收到2号就说明乱序了。

    • 收到乱序的数据怎么办?

      • 直接丢弃
      • 或者整个数组,先将其保存到它的正确位置上,等到都收齐了再一块递交给上层的协议处理。

        • 整个多大的数组(接收窗口)呢?
    • 对方怎么知道应该收到的第一个报文是1号呢?为什么不是89023号呢?每次标号必须都从1号开始标?

不多发也不少发

  • 如果接收到了两份一样的报文,怎么办?

    • 如果没有标号,我们可能就将两份一样的报文接收并递交给上层协议处理了。现在我们只需要忽略后来的一份就好了。
  • 如果迟迟没有收到应该发送到的报文,该怎么办?

    • 超时,让发送方重发。

其他的一些问题

  • 发送的数据过多,但是接收方的可用存储空间有限且处理速度赶不上发送速度,这会导致大量的包丢失。发了包没有用而且给网络带来了压力,可能造成了网络堵塞,此时如何限制发送方的发送速度?

    • 不断的反馈给发送方此时的可用空间,让发送方自行调整发送速度。
    • 那发送方如何调整速度呢? 发送窗口(为什么控制发送窗口的大小可以控制发送速度呢?报文是一个发送完之后等到成功接收之后再发送下一个的吗?)?
  • 如果我们接收到一个报文,通过标号来看它正是我们需要的报文,那么它就真的是我们所需要的吗?

    • client发送34号报文,server长时间没有收到34号报文,让client重发34号报文,之后server收到了34号报文。过了一段时间,server又需要34号报文了(只是标号一样,但是此时所需内容不同),此时之前迟迟未到的34号报文刚好到达,被server认为是自己当前所需的34号报文?

      • 注意的一点是TCP中的标号是用一个32位整数进行存储的,并不是无穷大的,所以这里的标号是循环使用的,0 1... max 0 1 ...
      • 发生的概率应该是很小的。
  • 接收方需要确认哪些报文已经被接收方成功接收了吗?

    • 发送方要什么会给我说的,我只需要发送给它要的就可以了。报文是按序接收的,当发送方需要34号报文的时候,说明之前的已经被成功接收了(累计确认)。

      • 如果对方接收到了,并且此时不需要不需要其他的报文了,那么就不回复了?此时发送方如何看待这种行为呢?

        • 接收方成功接收,且不再需要更多的报文
        • 接收方没有成功接收,让我重发的报文丢失了?等待超时之后我再重发。....会陷入一直重发的死循环。
      • 如果每次成功接收之后,都回复ACK的话。

        • 成功接收
        • 回复报文丢失。超时之后,重发,收到ACK,不会一直陷入死循环。
  • 发送方必须在等上一个发送的报文确认接收之后再发送另一个吗?

    • 不需要,可以同时发送多个。但是必须

      • 控制同时发送的数目(发送窗口的大小)
      • 记录发送报文的状态(已发送未确认、确认、未发送),来确定接下来发送或重发的报文。

    ....

所以在真正的发送有效数据之前,我们需要先传输一些实现可靠数据所需要的数据如起始标号是什么?接收窗口大小?发送窗口大小?最大报文段?...这就是我们先握手的原因。

那么为什么是3次呢?

A: 请求连接。并携带起始标号等信息。

此时的B会作何反应呢?
B: 我不同意连接。并发送ACK 起始标号(表明前一个报文被成功接收)等信息。

B: 同意连接。并发送起始标号,ACK等信息。(注:但是此时的连接还没有真正的建立,为什么?)

现在为了保证可靠数据传输所需的信息有了,现在就可以发送有效数据了?

但是这不是仅仅需要两次吗?为什么还要第三次呢?

在上面其他问题中提到如果我们接收到一个报文,通过标号来看它正是我们需要的报文,那么它就真的是我们所需要的吗
此时B最开始(此时,B并不需要任何特定标号的报文或者说任何编号都是可以接收的。这时,这种情况发生的概率就比较大了)接收的报文可不可能是之前的报文呢?所以我们还需要确认一番。
当A接收到ACK中的标号,查看是否是刚刚发送的

  • 如果不是,就告知B取消连接。
  • 如果是,就告知B确认连接,此时才真正的建立连接。

UDP没有上面握手的过程,它不提供可靠的数据传输,不能保证按需到达、没有重传机制、没有流量控制、拥塞控制。

It provides an unreliable connectionless transport service on top of the unreliable network layer connectionless service.
The main characteristics of the UDP service are :
  • the UDP service cannot deliver SDUs that are larger than 65467 bytes 1
  • the UDP service does not guarantee the delivery of SDUs (losses can occur and SDUs can arrive out-of-sequence)
  • the UDP service will not deliver a corrupted SDU to the destination

参考资料

问题1,你这里描述的就是udp协议了,udp协议就是没有三次握手,一开始就直接发送数据包的。

问题2,tcp中文名字就叫 传输控制协议 ,顾名思义,这个协议就是用来规定如何传输和控制报文的。

因为tcp设计出来的目的就是提供安全可靠的连接服务,所以要让报文变得可靠而且安全,所以就有一些保障传输安全可靠的措施。

比如

  • 给每个报文排序,要让报文按照顺序传输,通过排序的顺序,接受端就能知道中间有没有报文丢失。
  • 接受到报文后,返回ack确认收到报文。
  • 还有重传 拥塞控制 数据检验 滑动窗口等等

这里主要说排序和ack,握手的时候,主要目的就是让传输的双方确定建立连接,确定排序的号码,方便后面传输数据的时候对传输的报文进行校验。

核心原因,在于早期网络的高度不稳定性,互联网最初是美国为了在核战阴云下,被毁灭打击后还能继续维持部分幸存节点之间互相通讯而进行研究的项目,在这样的环境下,你首先要考虑的是可靠性问题。TCP的三次握手,本质是为了解决这个可靠性问题的产物。
就因为这个原因,所以TCP的很多设计都能看出是为了适应恶劣通讯环境而做的,比如默认的超时设置高达2小时。
楼主的问题在于它把现在这种动不动就是千M光纤,到处都是wifi,5G的良好网络基础设施当成理所当然了,自然就会困惑TCP这玩意发个包为啥要搞的这么麻烦。实际上现在我们已经有相当多的网络流量都是跑在UDP上的,就是因为网络基础设施的进步,使得UDP这种本来是不可靠传输的模式,现在变的基本可用了

小绿想给小红写小纸条,中间靠小黑传递。但是小黑这个人有点不靠谱,有时候会不小心把纸条丢掉,偶尔又发现没有丢掉只是放到口袋忘记了、这时又送了出去。

这天,小绿想约小红晚上八点一块去吃饭,就让小黑传了个纸条。结果小黑送到时,小红正在做作业,很是烦躁的说,没看到正忙着呢吗?随手把纸条扔到了垃圾桶。结果晚上八点,小绿终究没等到小红。

后来,小绿学聪明了,先让小黑传个纸条,问问小红这会有时间吗。有的话,他就要说正事了。小红回复说,这会有时间,快说吧。小绿说,晚上八点一起吃饭。小红收到消息后,很开心的回了一张小纸条:好的,晚上八点见。让小黑带回去。可惜回来时,小绿正在跟老师谈话,小绿看都没看就把小纸条扔垃圾桶了。结果晚上八点,小红终究没等到小绿。

后来,小红也学聪明了。每当小绿问小红这会有时间吗的时候,小红也会反问一下小绿这会有时间吗。当他们都有时间的时候,才能实现一起吃饭的愿望。

但是后面,他们发现小黑相当不靠谱。有时候丢纸条、有时候又把前几天的纸条传过来、有时候还会把纸条撕成好几片传过来、甚至还会用胶带绑一起传过来。完全不知道纸条上写的是什么?

小朋友,你能帮助一下小绿和小红吗?怎么才能让他们实现每天晚上八点都能一块吃饭吗?


  • 小红、小绿: 客户端、服务端
  • 小黑: 网络

tcp是可靠连接,握手之后双方发送数据包如果数据包在发送途中丢失可以触发重传。

握手的本质就是“确认”,就跟你在生活和工作中的确认是一样的:
“在吗”
“在”
“我待会给个好家伙你”
“好呀”
“那我现在传了噢”
……

宣传栏