当前位置: 首页 > 知识库问答 >
问题:

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

牟黎昕
2024-05-23

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

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

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

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

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

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

共有6个答案

轩辕阳焱
2024-05-23

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

袁宜民
2024-05-23

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

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

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

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

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

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


  • 小红、小绿: 客户端、服务端
  • 小黑: 网络
方昊英
2024-05-23

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

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

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

比如

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

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

邓光耀
2024-05-23
了解到三次握手的本质也是发送了数据包到对方电脑

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

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

参考资料

  • Computer Networking : Principles, Protocols and Practice, The User Datagram Protocol
  • Computer Networking : Principles, Protocols and Practice, The Transmission Control Protocol
丁星火
2024-05-23

参考

  • TCP 三次握手和四次挥手(传输层)
  • TCP 为什么是三次握手,而不是两次或四次? - 知乎

直接发数据发到一半包丢了怎么办,发送端无法确认接收端是否成功接收。

方韬
2024-05-23

问题1回答:

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

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

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

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

问题2回答:

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

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

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

 类似资料:
  • 本文向大家介绍Android中实现TCP和UDP传输实例,包括了Android中实现TCP和UDP传输实例的使用技巧和注意事项,需要的朋友参考一下 TCP和UDP在网络传输中非常重要,在Android开发中同样重要。 首先我们来看一下什么是TCP和UDP。 什么是TCP? TCP:Transmission Control Protocol 传输控制协议TCP是一种面向连接(连接导向)的、可靠的、基

  • 在实验运行在esp32上的UDP服务器时,我发现接收到的数据包的大小限制在1500字节: 20(IP头)8(UDP头)1472(数据),(尽管理论上UDP好像可以支持数据包64K)。这意味着,为了传输更大量的数据,客户端必须将其拆分成若干块并依次发送,而在服务器端,这些数据将需要恢复。我认为这种解决方案的管理费用将相当高。我还知道TOIT提供TCP/IP连接。自然,分组大小在TCP/IP的情况下也

  • 用的TypeScript。 我定义了一个函数组件:MyView: 可以正常使用: 为了看起简洁点,我将 MyView 稍微修改了一下: 这个时候调用的地方就报错了: 报错信息: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes & ReactNode'. Type '{ children: El

  • 所以,这可能是一个愚蠢的问题,但据我所知,如果我通过TCP或UDP发送数据,如果组成该TCP/UDP数据包的任何一个IP数据包被丢弃,整个TCP/UDP数据包将被重传,但我的问题是为什么我们不能只发送丢失的部分数据吗?目前,我对此的唯一推理是,如果我们要为收到的每个IP数据包发送确认字符,这将增加网络拥塞。这是正确的,还是有其他原因,当只有一个或几个IP数据包被丢弃时,我们必须重新发送TCP/UD

  • 我已经编写了一个服务器-客户端(两个程序)结构,它工作正常。。。仅当使用TCP时。我的想法是使用TCP进行文本聊天传输(udp不可靠),但使用udp进行游戏数据包传输(是的,这是一种每秒30帧的动作游戏,所以我需要udp)。 但是,当我在客户端进程中与TCP建立连接时,我开始向服务器程序发送UDP数据包,并从服务器程序接收UDP数据包。客户端在单个线程中使用非阻塞套接字、UDP和TCP。这里没有多

  • 本文向大家介绍python实现udp数据报传输的方法,包括了python实现udp数据报传输的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python实现UDP数据报传输的方法,非常具有实用价值。分享给大家供大家参考。具体方法分析如下: 服务端代码: 客户端代码: 结果:先运行服务端,然后运行客户端, 服务端打印出: 补充: socket.sendto(string[, flags