TCP/UDP

TCP详解

首先看报头


image.png

4位首部长度: 表示该tcp报头有多少个4字节(32个bit)
URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: 用来提示接收端应用程序立刻将数据从tcp缓冲区读走
RST: 要求重新建立连接. 我们把含有RST标识的报文称为复位报文段
SYN: 请求建立连接. 我们把含有SYN标识的报文称为同步报文段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报文称为结束报文段
16位校验和:此处的校验和不光包含TCP首部, 也包含TCP数据部分.
16位紧急指针: 用来标识哪部分数据是紧急数据.

这里可能会问,不是说TCP是面向字节流的吗?怎么会有报头格式
TCP/UDP面向字节流或报文是指对于上层来说的,TCP将应用层传递下来的数据当做看成无结构的字节流,TCP就像是蓄水池,等到可以发送的时候就发送,不能发送就等着,TCP会根据当前网络的拥塞状态来确定每个报文段的大小。

为什么三次握手

client发送的建立连接的请求可能会因为网络原因,滞后发送到server端,server端依然会发送链接确认的报文给client,如果为两次握手,client不会对其进行处理并且忽略,而server端并不知道client已经忽略而白白浪费了一定的资源。如果为三次握手,则server会因为收不到client的确认ACK报文而不建立连接。

为什么四次挥手

TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,TCP是全双工模式,当client发送FIN报文到server代表client已经没有数据要发送到server了,但是server还可以继续发送数据到client,直到server也发送FIN报文到client。


image.png
为什么client收到server的FIN后还要等待2*MSL

MSL是什么?他是最长报文段寿命,他表示的是具体时间,而IP中的ttl代表的是最大路有数,每次经过路由都会减1
1.保证客户端发送的最后一个ACK报文能够到达服务器,因为最后的ACK可能会丢失,允许server重新发送一次FIN报文
2.三次握手就是为了防止之前的连接请求报文,在这里也可以保证本次连接的所有报文都消失在网络中
client每次收到FIN后都会重新启动2MSL的计时器
cat /proc/sys/net/ipv4/tcp_fin_timeout可以查看MSL值

确认应答机制

TCP对每个字节都编写了编号,每一个ACK都带有对应的确认序列号,该确认序号为server想要收到的编号,并表示之前的编号均已收到

延迟应答
因为接受放在收到数据后要进行ack,返回接收窗口的大小,比如接收端缓冲区为1M. 一次收到了500K的数据,那么接收窗口为500K,但是数据处理相对较快,可能马上把缓冲区的数据消费掉了,所以延迟应答可以提高网络吞吐量
延迟应答的策略:
数量限制: 每隔N个包就应答一次
时间限制: 超过最大延迟时间就应答一次

捎带应答:在接收方发送ack的时候可以同时发送数据

超时重传机制

TCP在发送了数据后在特定时间间隔没有收到ACK则重传数据,由于有序号的确认应答机制,则能保证去重问题。
Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.如果重发一次之后, 仍然得不到应答, 等待 2500ms 后再进行重传. 如果仍然得不到应答, 等待 4500ms 进行重传.依次类推, 以指数形式递增. 累计到一定的重传次数, TCP认为网络异常或者对端主机出现异常, 强制关闭连接.

流量控制和滑动窗口

当流量超过网络硬件负荷时会导致网络拥塞,使用滑动窗口控制收发端传输数据的速度,维持传输平衡。
TCP报头中的窗口大小就是这个滑动窗口,窗口字段长度为16位,可以表示最大65535的值,即窗口最大为65535字节。这里发送的窗口大小为接收窗口的大小,发送方可以根据传过来的窗口大小以及ack来调整自己的发送窗口。

发送方:
image.png

当发送方收到ACK时,ack只可以移动窗口的左边界,窗口大小可以移动右边界,并且发送方可以根据自己已经发送并且未被确认的大小来调整即将发送的数据大小
接收方:
image.png

只有收到的数据序列号再左边界和右边界之间时,才会接收保存,这样窗口才会向前移动。

当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器。

一般接收窗口 》= 发送窗口,并且接收窗口不固定。

拥塞控制

流量控制与拥塞控制区别
流量控制虽然解决了在端已经知道网络情况下进行的策略,但是有可能因为网络一开始一股脑地发送了大量数据导致网络拥挤但是发送端并不清楚,这就需要拥塞控制了,它是全局性的控制,而流量控制是端到端的控制。

发送方维持一个拥塞窗口cwnd,所以发送方真正能发送的窗口大小为Min(cwnd, 接收方窗口值)
慢开始
在一开始cwnd为1,每经过一个传输轮次(一次发送加确认)则cwnd加倍
直到cwnd达到了ssthresh慢开始门限
拥塞避免
当cwnd达到了ssthresh则进入了拥塞避免,此时cwnd在每次传输轮次后仅增加1

快重传与快恢复
首先是怎么判断达到了拥塞状态:
1.重传定时器超时
2.收到3个重复的ACK

快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认
发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段M3,

快恢复为当判断达到了拥塞状态时并不将cwnd慢开始,而是将cwnd设置为ssthresh的一半并直接开始执行拥塞避免,新的ssthresh为旧的ssthresh一半。

SACK

在接收方收到失序报文时,会将该数据放到乱序序列中,并向发送方发重复ACK,此时发送方会发送ACK后的所有正确数据,这会导致重复发送,降低TCP性能。
SACK在发送ACK的时候会告诉发送方已经收到的失序数据,而此时发送方则只会发送丢失的数据。SACK只是在收到失序数据时才会发送,而超时和正常应答还是用的ACK

连接一方断电后会怎么样
  1. KEEPALIVE检测

如果接收方掉电,发送方在发送数据多次重试失败后会发送RST报文后转为close状态
如果发送方掉电

Nagle算法

nagle算法用于处理小报文段(微小分组)的发送问题,当交互型报文时一般传输的数据大小很小导致报文利用率很低。 极端情况下,有效载荷可能只有1个字节;而传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象就叫糊涂窗口综合症。
nagle保证网络中最多只能有一个分组被发送,其他待发送的小数据可以组成一个较大的分组等待上一个分组返回确认后发送。
nagle算法与延迟ack都是为了解决糊涂窗口综合征问题,但是方法确实背道而驰的。

粘包问题

tcp是面向字节流的,并不清楚上层具体传输数据的大小,造成了数据无边界问题。
解决:对于定长数据可以每次读取固定大小的数据即可;对于不定长的数据需要在数据报文内中限定每次读取的长度。

udp是不会有这种问题的,因为udp不会对数据进行合并的,每次发送的数据都是直接发送而不会合并成一个包发送,并且在接收方的缓冲区是以链式的方法将接收到的数据串联起来。

UDP

UDP是无状态,无连接的数据报协议,他面向的是数据报文。

image.png

其中长度为报头加报文,报头长度为8字节,所以可以看出UDP报文最大长度为2^16=65536字节。
而真正传输的大小肯定不可能最大是这个,需要考虑MTU值。如果UDP报文长度超过MTU,ip会进行分片,但是ip分片和组片对于UDP是透明的,UDP是并不知情的。
UDP是有界的!
UDP无论发送的数据大小是多少,在接收缓存中都是分界的,并且如果超过了缓冲区的大小,recvfrom的大小超过缓冲区大小则只会读取存在于缓冲区中的数据大小。
UDP是无序的,发送的顺序和接收的顺序不一定是一致的。

UDP和TCP的区别

1.面向连接/无连接
2.面向字节流/面向报文
3.可靠传输/非可靠传输
4.一对一/一对多,多对多
5.首部开销20字节 /8字节
6.有拥塞控制/无拥塞控制,所以网络堵塞不会导致源主机的发送速率变慢

IP地址

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。