写点什么

Linux 网络编程 -UDP 和 TCP 协议详解

发布于: 2021 年 06 月 05 日

1|0 二. 引言

网络协议是每个程序员都要掌握的基础知识,干啥都离不开网络,就算在家里新买了个路由器不是吗,同事连不上网,你的女朋友手机没有网看剧了正看到高潮部分,到那时候你打开百度......那嫌弃的你的眼神仿佛在说,就这?程序员连个网都不会修?以上都是臆想,以实际为准.虽然看完本文章,你还是需要去百度怎么修复网络问题,但是你已经知道为什么会出现这种问题了!

2|0 二. UDP

UDP 协议全称是用户数据报协议,在网络中它与 TCP 协议一样用于处理数据包,是一种无连接的协议.在 OSI 中,第四层传输层,处于 IP 协议的上一层 UDP 有不提供数据包分组,组装和不能对数据包进行排序的缺点,也就是说,当报文发送后,无法监控其是否完整安全到达的,就想一个坏掉了的水龙头,你不论怎么让他停止他都只会输出,也不管你的桶满没满,就像爱一样

文章相关视频讲解:

C/C++ Linux 服务器开发高级架构师学习视频点击:C/C++Linux服务器开发高级架构/Linux后台架构师-学习视频

底层原理到徒手实现 TCP/IP网络协议栈

tcpip协议栈与网络API的关联,udp的并发性比tcp强?

2|1 特点

1. 面向无连接:

首先 UDP 是不需要和 TCP 一样在发送数据前进行三次握手建立连接的,想发数据就可以开始发送了.并且也只是主句报文的搬运工,不会对数据报文进行任何拆分和拼接操作

具体来说:

  • 在发送端,应用层将数据传递给 UDP 协议,UDP 只会给数据增加一个 UDP 头标识下 UDP,然后就传递给网络层了

  • 在接收端,网络层将数据传递给传输层,UDP 只去除 IP 报头就传递给应用层,不会任何拼接操作

2. 有单播,多播,广播的功能

UDP 不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播和广播的功能.

3. UDP 是面向报文的

发送方的 UDP 读应用程序交下来的报文,在添加首部后就向下交付 IP 层.UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界.因此,应用程序必须选择合适大小的报文

4. 不可靠性

首先不可靠性体现在无连接上,通信不需要建立连接,想发就发,这样的情况肯定不可靠

并且受到什么数据就传递什么数据,并且也不会备份数据,发送数据也不会关心对方是否已经正确接收到数据了

再者网络环境时好时坏,但是 UDP 因为没有拥塞控制,一直会以恒定的速度发送数据,即使网络条件不好,也不会对发送数据进行调整.这样实现的弊端就是在网络条件不好的情况下会导致丢包,但是有点也很明显,比如电话会议等等最好就是 UDP

5. 头部开销小,传输数据报文是很高效的.

因此 UDP 的头部开销小,只有八字节,相比 TCP 的至少二十字节要少得多,在传输数据报文时是很高效的

3|0 三. TCP/IP 网络模型

计算机网络设备相互通信,双方必须基于相同的方法.比如如何探测到通信目标,由那一边先发起通信,使用哪种语言进行通信,怎样结束通信等规则都需要实现确定.不同硬件,操作系统之间的通信,所有的这一切都需要一种规则,而我们吧这种规则成为协议.

TCP/IP 是互联网相关的各类协议的总称,比如:**TCP,UDP,IP,FTP,HTTP,ICMP,SMTP **等都属于 TCP/IP 族内的协议

大家一定知道 OSI 七层模型,TCP/IP 概念模型是这样的

  • 应用层:负责向用户提供应用程序.比如 HTTP,FTP,Telnet,DNS,SMTP 等

  • 传输层:负责对报文进行分组和重组,并以 TCP 或 UDP 协议格式封装报文

  • 网络层:负责路由以及把分组报文发送给目标网络或主机

  • 链路层:负责封装和接缝 IP 报文,发送和接收 ARP/RARP 报文等

4|0TCP

当一台计算机想要与另一台计算机通讯时,两台计算机之间的通信需要畅通且可靠,这样才能保证正确收发数据.例如当你收文件时候不希望收到的是一个损坏的文件,发过来的小电影是无法放映的,或者直接变成马赛克,当然也可能本来就有马赛克,这不是我们希望得到的,于是就用到了 TCPTCP 协议全称是传输控制协议,,这是一种面向连接的,可靠的,基于字节流的传输层通信协议

4|1TCP 的连接过程

TCP 报文也分为首部和数据两部分,首部默认情况下一般是 20 字节长度,但在 20 字节长度,但在一些请求情况下,会使用"可选字段",这时,首部长度会有所增加,但最长不超过 60 字节

关于 C/C++ Linux 后端开发网络底层原理知识 点击 学习资料 获取,内容知识点包括 Linux,Nginx,ZeroMQ,MySQL,Redis,线程池,MongoDB,ZK,Linux 内核,CDN,P2P,epoll,Docker,TCP/IP,协程,DPDK 等等。

源端口 - 16bit  

来源处的端口号;端口号有 65536 个,即 $2^{16}$。

目的端口 - 16bit  

目的处的端口号

序号 - 32bit  

TCP 在对数据进行分段的时候,会给每一个 TCP 报文段添加一个序号,序号字段的值其实是该文段所发送的数据的第一个字节的序号。这么做的原因是,TCP 是面向连接的可靠服务,这个序号可以保证数据在传输过程中保持有序性,接受端可以通过这个序号确认收到的数据的完整性和先后顺序;

确认号 - 32bit  

确认号,是期望收到对方的下一个报文段的数据的第一个字节的序号;

数据偏移 - 4bit  

其实它本质上就是“首部长度”,因为“数据偏移”是指 TCP 报文段的数据部分的起始处距离 TCP 报文段的起始处的距离。(仍然很拗口,但相信你能明白)。  

数据偏移总共占 4bit,因此最大能表示的数值为 15。但 TCP 的报文头部至少为 20 字节。因此数据偏移的单位是“4 字节”,此处的设计和 IP 数据报的设计是完全相同的,所以说 TCP 报文段首部的长度最长为 15×4=60 字节,且首部长度必须为 4 字节的整数倍。

保留字段 - 6bit  

IETF 文档指出,这 6bit 在标准中是保留字段,留待以后使用,必须为 0。我猜测,有两个目的,第一个是预留除 URG/ACK/PSH/RST/SYN/FIN/之外的冗余功能位;第二个是为了对齐字节位。

控制位 - 6bit

又称为 TCP flag,该字段从左到右分为以下六个字段,指明包的类型。同时用于控制 TCP 的状态机,同时 ACK 和 SYN 与三次握手协议有关,FIN 与四次挥手协议有关。  

① 紧急字段 URG - 1bit    

当 URG=1 时,此字段告诉系统此报文段中有紧急数据,应尽快传送。  

② 确认字段 ACK - 1bit    

当 ACK=1 时,表示确认,且确认号有效;当 ACK=0 时,确认号字段无效。  

③ 推送字段 PSH - 1bit    

当 PSH=1 时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略。  

④ 复位字段 RST - 1bit    

当 RST 为 1 时,表明 TCP 连接中出现了严重的差错,必须释放连接,然后再重新建立连接。  

⑤ 同步字段 SYN - 1bit    

当 SYN=1 时,表示发起一个连接请求。  

⑥ 终止字段 FIN - 1bit    

用来释放连接。当 FIN=1 时,表明此报文段的发送端的数据已发送完成,并要求释放连接。

窗口字段 - 16bit  

此字段用来控制对方发送的数据量,单位为字节。  

一般 TCP 连接的其中一端会根据自身的缓存空间大小来确定自己的接收窗口大小,然后告知另一端以确定另一端的发送窗口大小。该字段与 TCP 的流量控制服务有关。

校验和字段 - 16bit  

与 IP 协议的检验和不同,TCP 的这个校验和是针对首部和数据两部分的。

紧急指针字段 - 16bit  

紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。

4|2 三次握手四次挥手(这词都听吐了,换个叫法:一键三连,取消三连加取关/滑稽))

还有一点其实人家是 Three-way handshake,三步握手四步挥手的,谁握手握三次,挥手挥四次的,/吃瓜 TIP:注意箭头的指向,结合文字进行理解,箭头没有问题

1. 一键三连

在三连之前服务器和客户端都为 CLOSED 状态.通信开始前,双方都得创建各自的传输控制块(TCB)服务器创建完 TCB 后便进入 LISTEN 状态此时准备接受客户端发来的连接请求

点赞(第一次握手)

客户端向服务端发送连接请求报文段.该保温段的头部中 SYN=1,ACK=0,seq=X.请求发送后客户端便进入 SYN-SENT 状态

  • SYN = 1,ACK = 0 表示该报文段位连接请求报文

  • x 为本次 TCP 通信的字节流的初始序号

TIP:TCP 规定 SYN = 1 的报文段不能有数据部分,但要消耗一个序号

投币(第二次握手)

服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN = 1,ACK = 1,seq = y,ack = x + 1 该应答发送完成后便进入 SYN-RCVD 状态.

  • SYN=1,ACK=1 表示该报文段为连接同意的应答报文

  • seq=y 表示服务端作为发送者时,发送字节流的初始序号

  • ack=x+1 表示服务端希望下一个数据报发送序号从 x+1 开始的字节

收藏(第三次握手)

当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示服务端发来的连接同意应答已经收到该报文头部为:ACK = 1, seq = x + 1, ack = y + 1.客户端发完这个报文后便进入 ESTABLSHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接的建立完成

2. 取消三连加取关

TCP 连接的释放一共需要四部,因为 TCP 连接时双向的,因此在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向连接

取消点赞(第一次挥手)

若客户端认为数据发送完成,则它需要向服务端发送连接释放请求.该请求只有报文头,头中携带的主要参数为:FIN = 1,seq = u 此时,客户端将进入 FIN-WAIT-1 状态

  • FIN = 1 表示该保温是一个连接释放请求

  • seq = u,u - 1 是 A 向 B 发送的最后一个字节的序号

取消投币(第二次挥手)

服务端收到连接释放请求后,会通知相应的应用程序,告诉它客户端向服务端这个方向的连接已经释放.此时服务端进入 CLOSE-WAIT 状态,并向客户端发送连接释放的回答,其报文头包含:ACK = 1,seq = v, ack = u + 1

  • ACK=1:除 TCP 连接请求报文段以外,TCP 通信过程中所有数据报的 ACK 都为 1,表示应答。

  • seq=v,v-1 是 B 向 A 发送的最后一个字节的序号。

  • ack=u+1 表示希望收到从第 u+1 个字节开始的报文段,并且已经成功接收了前 u 个字节

客户端收到应答进入 FIN-WAIT-2 状态,等待服务端发送连接释放请求第二次挥手完成后,客户端到服务端方向的连接已经释放,服务端不会接受数据,客户端也不会发送数据,但服务端到客户端的连接仍然存在,服务端可以继续向客户端发送数据

取消收藏(第三次挥手)

当服务端发送完所有数据后,向客户端发送连接释放请求,请求头:FIN = 1,ACK, seq = w,ack = u+1.服务端便进入 LAST-ACK 状态.

取消关注(第四次挥手)

当客户端收到释放请求后向 B 发送确认应答,此时客户端进入 TiME-WAIT 状态,该状态会持续 2MSL(2 分钟)时间,若该时间没有服务端重发请求的话,就进入 CLOSED 状态,撤销 TCB.当服务端收到确认应答后,也进入 CLOSED 状态撤销 TCB

用户头像

Linux服务器开发qun720209036,欢迎来交流 2020.11.26 加入

专注C/C++ Linux后台服务器开发。

评论

发布
暂无评论
Linux网络编程-UDP和TCP协议详解