1. UDP协议
用户数据报协议UDP只在IP的数据报服务至上增加了复用和分用的功能以及差错检测的功能。
只有面向无连接的报文,不可靠传输的特点。
UDP对应用层交下来的数据只添加首部,并进行特别的处理,就交给网络层;对网络层传递上来的用户数据报拆封首部后,原封不动的交给应用层。
1.1 UDP的首部格式
用户数据报UDP分为两个字段:数据字段和首部字段
UDP首部字段很简单,由4个字段组成,每个字段的长度都是两个字节,共8字节。
- 源端口 原端口号,在需要对方回信时选用,不需要时可全0
- 目的端口 目的端口号,这在终点交付报文时必须使用,不然数据交给谁呢?
- 长度 UDP的长度,最小值为8字节,仅有首部
- 检验和 检测用户数据报在传输过程是否有错,有错就丢弃。
在传输的过程中,如果接收方UDP发现收到的报文中的目的端口不存在,会直接丢弃,然后由网际控制报文协议ICMP给发送方发送“端口不可达”差错报文。
2. TCP协议
TCP协议作为传输层主要协议之一,具有面向连接,端到端,可靠的全双工通信,面向字节流的数据传输协议。
2.1 TCP协议介绍
虽然TCP面向字节流,但TCP传输的数据单元却是报文段。
TCP报文段分为TCP首部和数据部分,TCP报文段首部的前20个字节是固定的,后面有4*n字节根据需要动态添加的选项,最大长度为40字节。
-
源端口和目的端口 各占两个字节,TCP的分用功能也是通过端口实现的。
-
序号 占4个字节,范围是[0,232],TCP是面向字节流的,每个字节都是按顺序编号。例如一个报文段,序号字段是201,携带数据长度是100,那么第一个数据的序号就是201,最后一个就是300。当达到最大范围,又从0开始。
-
确认号 占4个字节,是期望收到对方下一个报文段的第一个字节的序号。若确认号=N,则表示序号N前所有的数据已经正确收到了。
-
数据偏移 占4位,表示报文段的数据部分的起始位置,距离整个报文段的起始位置的距离。间接的指出首部的长度。
-
保留 占6位,保留使用,目前为0.
-
URG(紧急) 当URG=1,表明紧急指针字段有效,该报文段有紧急数据,应尽快发送。
-
ACK(确认) 仅当ACK=1时,确认号才有效,连接建立后,所有的报文段ACK都为1。
-
PSH(推送) 接收方接收到PSH=1的报文段,会尽快交付接收应用经常,不再等待整个缓存填满再交付。实际较少使用。
-
RST(复位) RST=1时,表明TCP连接中出现严重差错,必须是否连接,再重连。
-
SYN(同步) 在建立连接时用来同步序号。当SYN=1,ACK=0,则表明是一个连接请求报文段。SYN=1,ACK=1则表示对方同意连接。TCP建立连接用到。
-
FIN(终止) 用来释放一个连接窗口。当FIN=1时,表明此报文段的发送方不再发送数据,请求释放单向连接。TCP断开连接用到。
-
窗口 占2个字节,表示发送方自己的接收窗口,窗口值用来告诉对方允许发送的数据量。
-
校验和 占2字节,检验和字段查验范围包括首部和数据部分。
-
紧急指针 占2字节,URG=1时,紧急指针指出本报文段中的紧急数据的字节数(紧急字节数结束后为普通字节)。
-
选项 长度可变,最长可达40字节。例如最大报文段长度MSS。MSS指的是数据部分的长度而不是整个TCP报文段长度,MSS默认为536字节长。窗口扩大,时间戳选项等。
2.2 TCP的三次握手
对于TCP三次握手和四次挥手,主要的是相互交换确认序列号,我们最主要的就是关注TCP头部的序列号、确认号以及几个标记位(SYN/FIN/ACK/RST)
- 序列号:在初次建立连接的时候,
客户端和服务端都会为「本次的连接」随机初始化一个序列号。(纵观整个TCP流程中,序列号可以用来解决网络包乱序的问题) - 确认号:该字段表示「接收端」告诉「发送端」对上一个数据包已经成功接收(
确认号可以⽤来解决网络包丢失的问题) - 标记位:
SYN为1时,表示希望创建连接。ACK为1时,确认号字段有效。FIN为1时,表示希望断开连接。RST为1时,表示TCP连接出现异常,需要断开。
-
第一次:客户端发送连接请求报文给服务端,其中
SYN=1, 客户端随机生成序列表seq=x。发送完毕后进入SYN_END状态。 -
第二次:服务端接收到报文后,
发回确认报文其中ACK=1, 确认号ack=x+1,因为需要客户端确认,所以报文中也有SYN=1,服务端随机生成序列号seq=y的信息。发送完后进入SYN_RCVD状态。 -
第三次:客户端接收到报文后,发送确认报文,
其中ACK=1,确认号ack=y+1。发送完客户端进入ESTABLISHED状态,服务端接收到报文后,进入ESTABLISHED状态。到此,连接建立完成。
2.4 三次握手的相关问题?
- 为什么需要三次握手?
一次握手:肯定建立不了连接,因为没法判定是否发送成功。
两次握手: 只能保证客户端的序列号成功被服务端接收,而服务端是无法确认自己的序列号是否被客户端成功接收。
三次握手:可以保证任何一次握手的失败都是可感知的,不会浪费资源。
四次握手:没有必要,三次足矣。
- 序列号为什么随机生成的?
一方面为了安全性(随机ISN能避免非同一网络的攻击)
一方面可以让通信双方能够根据序号将「不属于」本连接的报文段丢弃。
- 网络不可靠,创建连接的时候中途丢失了怎么办?
第一个包丢了: 客户端发送给服务端的 SYN 包丢了(简而要之就是服务端没接收到客户端的SYN包).
客户端迟迟收不到服务端的ACK包,那会周期性超时重传,直到收到服务端的ACK.
第二个包丢了: 服务端发送的SYN+ACK包丢了(简而要之就是客户端没接收到服务端的SYN+ACK包).
服务端Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,TCP才会把断开这个连接.
第三个包丢了: 客户端发送完第三个包后单方面进入了 ESTABLISHED 状态,而服务端也认为此时连接是正常的,但第三个包没到达服务端.
如果此时客户端与服务端都还没数据发送,那服务端会认为自己发送的SYN+ACK的包没发送至客户端,所以会超时重传自己的SYN+ACK包
2.3 TCP的四次挥手
第一次挥手:客户端发送FIN=1,客户端随机生成的序列号seq=u的包给服务端,表示自己没有数据要进行传输,单面连接传输要关闭。发送完后,客户端进入FIN_WAIT_1状态.
第二次挥手:服务端收到请求包发回 ACK=1 , ack=u+1的确认包,表示确认断开连接。服务端进入CLOSE_WAIT状态。客户端收到该包后,进入FIN_WAIT_2状态。此时客户端到服务端的数据连接已断开.
第三次挥手:服务端发送确认ACK=1,ack=u+1 , 关闭FIN=1,随机生成的序列号seq=w的包给客户端,表示自己没有数据要给客户端了。发送完后进入LAST_ACK状态,等待客户端的确认包。
第四次挥手:客户端收到请求包后,发送确认ACK=1,ack=w+1的确认包给服务端,并进入TIME_WAIT状态,有可能要重传确认包。服务端收到确认包后,进入CLOSED状态,服务端到客户端的连接已断开。客户端等到一段时间后也会进入CLOSED状态。
2.3.1 四次握手的问题?
- 为什么是四次?
TCP是全双工模式
当主机A发出FIN报文段时,只是表示主机A已经没有数据要发送了,但是这个时候主机1还是可以接受来自主机B的数据;
当主机B返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机B还是可以发送数据到主机A的;
当主机B也发送了FIN报文段时,这个时候就表示主机B也没有数据要发送了,就会告诉主机A,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。
- TIME_WAIT 这个状态是干什么的?为什么需要等待2MSL?
MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
1. 假设主机A如果直接在CLOSED:
如果网络问题导致主机B没有收到主机A最后回复的ACK,那么主机B就会在超时之后继续发送FIN,此时由于主机A已经CLOSED了,就找不到与重发的FIN对应的连接。
如果保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
2. 如果小于2MSL,第一个连接结束,第二个拥有相同的连接出现,而第一个连接的重复报文出现,干扰第二个连接。就会出现某个连接的重复报文在连接终止后出现。
- TIME_WAIT 状态过多会有什么危害?
如果系统中有很多socket处于TIME_WAT状态,当需要创建新的 socket连接的时可能会受到影响.
一个Socket如果关闭的话,它将保持TIME_WAIT状态大约1-4分钟.
如果很多连接快速的打开和关闭的话系统中处于TIME_WAIT状态的 由于本地端口数量的限制.
同一时间只有有限数量的 socket连接可以建立,由于用于新建连接的本地端口太缺乏将会很难再建立新的
- 查看当前系统的连接状况
netstat -n|awk '/^tcp/{++S[$NF]}END{for (key in S) print key,S[key]}'
- TIME_WAIT 过多开启端口复用
通过调整内核参数解决:编辑文件/etc/sysctl.conf,加入以下内容:
net.ipv4.tcp_syncookies = 1 //表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;\
net.ipv4.tcp_tw_reuse = 1 //表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;\
net.ipv4.tcp_tw_recycle = 1 //表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。\
net.ipv4.tcp_fin_timeout =30 //修改系默认的 TIMEOUT 时间
2.4 TCP的流量控制
如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。
在连接建立时,B告诉了A:“我的接收窗口是 rwnd = 400 ”(这里的 rwnd 表示 receiver window) 。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。
请注意,TCP的窗口单位是字节,不是报文段。
TCP为每一个连接设有一个持续计时器(persistence timer)。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口控测报文段(携1字节的数据),那么收到这个报文段的一方就重新设置持续计时器。
2.5 TCP的拥塞控制
2.5.1 什么是拥塞?
什么是拥塞呢,在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就会变坏了,这种情况就叫拥塞。网络资源常指网络链路容量(带宽)、交换结点中的缓存和交换处理机。
当出现拥塞,条件允许一般都是通过添加网络资源,例如带宽换成更大的,但这治标不治本,而且不一定总是有用。网络拥塞往往是有许多因素引起的,因此就需要拥塞控制了。
2.5.2 拥塞控制
拥塞控制指防止过多的的数据注入到网络中,这样可以使网络中的路由器或链路不过载。拥塞机制是一个全局性的过程,涉及到所有主机、所有路由器,以及与降低网络传输性能有光的所有因素。
而滑动窗口协议的流量控制,是指点到点的通信量控制,是端到端的问题。
2.5.3 TCP拥塞控制的方法
TCP进行拥塞控制的算法有四种:慢开始、拥塞避免、快重传、快恢复。 拥塞控制是基于拥塞窗口的,发送方维持一个拥塞窗口 cwnd的状态变量。窗口大小取决网络的拥塞程度,并且动态变化,发送方会让自己的发送窗口等于拥塞窗口。判断网络拥塞的依据就是发送方接收接收方的确认报文是否超时。
3. TCP和UDP的区别
-
可靠性;TCP是可靠的,UDP不不可靠的
-
TCP的面向连接的,UDP是面向无连接的
-
有序性。TCP在接受数据后是有序的。UDP则是无序的
-
速度。TCP速度比较慢,因为要创建连接。UDP则比较快,比较适合实时应用
-
量级。TCP是重量级的,头部大小在20-60;UDP则是轻量级的,头部大小在8个字节
-
应用场景。TCP 一般用于文件传输、发送和接收邮件、远程登录等场景。 UDP 一般用于即时通信,实时应用,比如: QQ 语音、 QQ 视频 、直播等等
4. Sockte和TCP/UDP关系
它的本质就是一套API接口,本质不属于网络协议,封装了 tcp/udp 协议,使用 socket 就相当于非常方便的直接与传输控制层打交道。
Socket通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket,一个Socket由一个IP地址和一个端口号唯一确定。应用程序通常通过“套接字”向网络发送请求或者应答网络请求。Socket是TCP/IP协议的一个十分流行的编程界面,但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。
5. 链接
-mp.weixin.qq.com/s/Pw8v6sZy9… -juejin.cn/post/704505… -juejin.cn/post/684490…