TCP(三次握手)和UDP(面向无连接)的原理以及区别
网络协议是每个前端工程师都必须要掌握的知识,TCP/IP 中有两个具有代表性的传输层协议。
概述
📡TCP(Transmission Control Protocol)是一种网络协议,用于设备在互联网上进行通信,它通过三次握手等机制确保传输可靠性和完整性。它是TCP/IP协议套件中的主要协议之一,提供错误检测和纠正功能,被广泛应用于各种领域,包括Web浏览、电子邮件、文件传输等。
📡UDP (用户数据报协议)是一种无连接的协议,运行在IP(互联网协议)之上。与TCP不同,UDP在发送数据之前不建立连接。UDP是一种更简单、更快速的协议,它专注于发送数据包,而无需进行错误检查、重传或保证传输的可靠性,也就是说当报文发送之后,是无法得知其是否安全完整到达的。
🔧TCP和UDP之间的区别
TCP是面向连接的,而UDP是基于连接的,需要进行三次握手建立连接:
对于UDP协议是面向无连接的 ,也就是说不需要在正式传递数据之前先连接对方。然后UDP协议只是数据报文的搬运工,在传输过程中可能会出现丢包 ,不保证有序且不丢失的传递到对方,并且UDP也没有任何控制流量的算法 ,但正因为这些因素从而使它的传输速率更加的高效 ,体现了它的实时性;
对于TCP是面向连接 ,它与UDP基本是反着来的,建立连接需要先进行握手 ,在数据传输过程中,通过各种算法保证数据传输的可靠性,但相对UDP,TCP的传输速率又慢了些。
🔮举个例子:
在我们生活中,我们需要把一堆零件移到另外一个地方的时候,如果我们使用UDP,那么就是直接使用铲车一次性把这些零件放过去,至于路上掉了多少它不管,只管把大部分零件送到,这样的UDP快速但不可靠;如果我们使用了TCP,那么我们会先把零件尽然有序的分类开,并依次打包发送,保证每一个零件通过专门的算法通道准确无误地到达目的地,如果路上掉了它还会通过算法去找,这样的TCP有序且可靠。
TCP与UDP头部的区别:
从两张图可以看出TCP的头部比UDP头部复杂的多。
🔆TCP的通信过程:
三次握手✋、确认传输📶、四次挥手✋,三次握手是建立连接的过程。
🌌三次握手
我们重点了解一下TCP重要的头部字段:
Sequence number:这个序号保证了 TCP 传输的报文都是有序的,对端可以通过序号顺序的拼接报文
Acknowledgement Number:这个序号表示数据接收端期望接收的下一个字节的编号是多少,同时也表示上一
个序号的数据已经收到。
Window Size:窗口大小,表示还能接收多少字节的数据,用于流量控制标识符。
URG=1:该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针
有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。
ACK=1:该字段为一表示确认号字段有效。此外,TCP 还规定在连接建立后传送的所有报文段都必须把
ACK 置为一。
PSH=1:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。
RST=1:该字段为一表示当前 TCP 连接出现严重问题,可能需要重新建立 TCP 连接,也可以用于拒绝
非法的报文段和拒绝连接请求。
SYN=1:当SYN=1,ACK=0时,表示当前报文段是一个连接请求报文。当SYN=1,ACK=1时,表示当前
报文段是一个同意建立连接的应答报文。
FIN=1:该字段为一表示此报文段是一个释放连接的请求报文。
💬当客户端向服务端发起连接时,会先发一包连接请求数据,过去询问一下,能否与你建立连接?这包数据称之为SYN包,如果对端同意连接,则回复一包SYN+ACK包,客户端收到之后,发送一包ACK包,连接建立,因为这个过程中互相发送了三包数据,所以称之为三次握手。
首先假设主动发起请求的一端称为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP 连接建立完后都能发送和接收数据,所以 TCP 是一个全双工的协议。
起初,两端都为 CLOSED 状态。在通信开始前,双方都会创建 TCB。 服务器创建完 TCB 后便进入 LISTEN 状态,此时开始等待客户端发送数据。
🚀第一次握手
客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入SYN-SENT 状态。
🚀第二次握手
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。
🚀第三次握手
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入
ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。
第三次握手中可以包含数据,通过快速打开(TFO)技术就可以实现这一功能。其实只要涉及到握手的协议,都可以使用类似 TFO 的方式,客户端和服务端存储相同的 cookie,下次握手时发出 cookie 达到减少 RTT 的目的。
接下来我们思考一个问题:💎为什么 TCP 建立连接需要三次握手,明明两次就可以建立起连接。
原因:为了防止出现失效的连接请求报文段被服务器端接收的情况,产生错误。
🚩例子:
客户端发送了一个连接请求A,但是因为网络原因造成了超时,这时TCP会启动超时重传的机制再次发送一个连接请求B,此时请求顺利到达了服务器,服务端应答完就建立了请求,然后接收数据后释放了连接;
🚩假如说:这时候连接请求A在两端都关闭后才到达服务端,那么此时服务端会误以为又需要建立TCP连接,从而应答了请求A并进入了ESTABLISHED 状态,但是客户端却是CLOSED的状态,那么会导致服务端一直等待客户端响应,从而造成资源的浪费。
🏮在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYNFlood 攻击。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求。
👐 四次解手
TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK。
🍪第一次解手
若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。
🍪第二次解手
B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。
🍪第三次解手
B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。
通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。
🍪第四次解手
A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。
🎿为什么 A 要进入 TIME-WAIT 状态,等待 2MSL 时间后才进入 CLOSED 状态?
为了保证 B 能收到 A 的确认应答。若 A 发完确认应答后直接进入 CLOSED 状态,如果确认应答因为网络问题一直没有到达,那么会造成 B 不能正常关闭。
今天的分享就到这里啦,感谢大家的阅览,小江会一直与大家一起努力,文章中如有不足之处,你的支持是我前进的最大动力,请多多指教,感谢支持,持续更新中 ......