常用协议 | |
---|---|
应用层 | HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(简单邮件传输协议)、DNS(域名系统)、DHCP(动态主机配置协议)、SNMP(简单网络管理协议) |
运输层 | TCP(传输控制协议)、UDP(用户数据报协议)、SCTP(流控制传输协议)、DCCP(数据报式传输协议) |
网络层 | IP(Internet Protocol) 、ICMP(Internet Control Message Protocol)、ARP(地址解析协议)、RAR(逆地址解析协议)、OSPF(开放最短路径优先)、BGP(边界网关协议) |
链路层 | PPP(点对点协议)、HDLC(高级数据链路控制)、Ethernet(以太网)、Wi-Fi(无线局域网)、ATM(异步传输模式)、FDDI(光纤分布式数据接口) |
物理层 | IEEE 802.3(以太网)、IEEE 802.11(Wi-Fi)、SONET(同步光纤网络)、DSL(数字用户线路)、USB(通用串行总线)、HDMI(高清晰度多媒体接口) |
机制 | 说明 |
---|---|
检验和 | 检测在一个传输分组中的比特错误 |
定时器 | 超时重传,接收方可能会收到一个分组的多个冗余副本 |
序号 | 空隙可使接收方检测出丢失的分组。相同序号的分组可使接收方检测出冗余副本 |
确认 | 确认报文通常携带着被确认的分组或多个分组的序号。确认可以是逐个的或累积的,取决于协议 |
否定确认 | 否定确认报文通常携带着未被正确接收的分组的序号 |
窗口、流水线 | 发送方也许被限制仅发送那些序号落在一个指定范围内的分组。通过允许一次发送多个分组但未被确认,发送方的利用率可在停等操作模式的基础上得到增加。窗口长度可根据接收方接收和缓存报文的能力、网络中的拥塞程度或两者情况来进行设置 |
连接:用于保证可靠性和流量控制维护的某些状态信息的组合,包括Socket、序列号和窗口大小
TCP四元组唯一确定一个连接:(源地址,源端口,目的地址,目的端口)
- 序号:解决包的乱序
- 确认序列:解决丢包
- 窗口大小:流量控制、拥塞控制的缓存大小
状态位
队头阻塞
- MTU(Maximum Transmission Unit)(最大传输单元):一个网络包的最大长度
- MSS(Maximum Segment Size)(最大分段大小):除去IP和TCP头部后,一个网络包容纳TCP数据的最大长度
客户端和服务端的初始化序列号都是随机生成,能很大程度上避免历史报文被下一个相同四元组的连接接收,然后又引入时间截的机制,从而完全避免了历史报文被接收的问题
TCP协议中的时间戳选项(Timestamp Option)用于在TCP报文段中携带时间戳信息。时间戳机制旨在提供更精确的计时和延迟测量,以及解决一些与序列号回绕相关的问题。
时间戳选项由TCP报文段的TCP头部中的"Options"字段中的一个选项来表示。时间戳选项包含以下字段:
TCP的时间戳机制具有以下作用和特点:
如果发现收到的数据包中时间截不是递增的,则表示该数据包过期,就会直接丢弃这个数据包
客户端A和客户端B因为经过相同的NAT网关服务端建立TCP连接,所以是用相同的IP地址与服务端建立TCP连接。如果客户端B的timestamp比客户端A的timestamp小,那么由于服务端的per-host的PAWS机制(同时开启net.ipv4.tcp_timestamps和net.ipv4.tcp_tw_recycle时触发),服务端就会丢弃客户端主机B发来的SYN包
握手丢失,导致超时重传,每次等待的RTO(Retransmission Timeout,超时重传时间)翻倍
查看最大重传次数:
cat /proc/sys/net/ipv4/tcp_syn_retries
cat /proc/sys/net/ipv4/tcp_synack_retries
第一次握手丢失
若第二、三次握手丢失,ACK报文不会重传,而是由对方重传
第二次握手丢失
第三次握手丢失
服务端每收到一个SYN,就进入SYN_RCVD状态,但发出的ACK+SYN报文无法得到ACK应答,进而占满服务端的半连接队列(SYN队列),后续再收到SYN报文会丢弃
半连接队列等待第三次握手,取出对应的IP端口的连接
当服务器收到一个SYN请求时,它会生成一个加密的cookie,其中包含了一些关键的连接信息,如源IP地址、端口号等。
服务器将生成的cookie作为序列号的一部分,将SYN+ACK响应发送给客户端。响应中的序列号包含了加密的cookie,以便客户端在后续的ACK确认中提供该cookie进行验证。
客户端在收到服务器的SYN+ACK响应时,会解析响应中的序列号,并提取出加密的cookie。
当客户端发送ACK确认时,它会将之前接收到的cookie作为有效凭证一起发送给服务器。
服务器在接收到ACK确认时,会对接收到的cookie进行解密和验证。如果验证通过,服务器会根据cookie中的信息重建连接状态,完成TCP连接的建立。
条件:被动关闭方没有数据要发送、开启了TCP延迟确认机制
延迟确认(见下面的“糊涂窗口”)
- close函数,同时socket关闭发送方向和读取方向,也就是socket不再有发送和接收数据的能力。如果有多进程/多线程共享同一个socket,如果有一个进程调用了close关闭只是让socket引用计数-1,并不会导致socket不可用,同时也不会发出FIN报文,其他进程还是可以正常读写该socket,直到引用计数变为0,才会发出FIN报文。
- shutdown函数,可以指定socket只关闭发送方向而不关闭读取方向,也就是socket不再有发送数据的能力,但是还是具有接收数据的能力。如果有多进程/多线程共享同一个socket,shutdown则不管引用计数,直接使得该socket不可用,然后发出FIN报文如果有别的进程企图使用该socket,将会受到影响。
第一次挥手丢失
第二次挥手丢失
第三次挥手丢失
FIN_WAIT2的最大时长默认为60秒
第四次挥手丢失
RTT(Round-Trip Time,往返时延)
RTO应略大于RTT
Selective Acknowledgement
在TCP头部“选项”字段添加SACK,将已收到的数据信息发给发送方,从而只传丢失的数据
无需等待确认应答,而可以继续发送数据的最大值;实际是缓存空间
接收窗口大小约等于发送窗口
发送窗口
发送方收到ACK确认后,可用窗口增加,即窗口滑动(否则可能导致队头阻塞)
接收窗口
收到有序数据时,窗口滑动(否则可能导致队头阻塞)
发送方根据接收方的实际接收能力,控制发送的数据量(避免发送方的数据填满接收方的缓存)
必须先收缩窗口,再减少缓存,否则可用窗口可能为负值,导致丢包
让接收方不通告小窗口给发送方;让发送方避免发送小数据
Nagle算法
延迟确认
避免发送方的数据填满网络
发送窗口swnd = min(接收窗口rwnd,拥塞窗口cwnd)
逐渐提高发送数据包的数量
发送方每收到一个ACK,cwnd就加1
cwnd < 慢启动门限ssthresh 时,使用慢启动算法,否则使用“拥塞避免算法”
发送方每收到一个ACK,cwnd就加1/cwnd
后半段由指数增长变为线性增长
超时重传
查看cwnd的初始化值
快速重传
Packet Number严格递增
Stream类型
Offset:类似于TCP协议中的Seq序号,保证数据的顺序性和可靠性
丢包重传时,Packet Number严格递增,比较两个数据包的StreamID与StreamOffset,若一致,就说明这两个数据包的内容一致,为重传的数据包
QUIC给每一个Stream都分配了一个独立的滑动窗口
Stream可以认为就是一条HTTP请求,每个Stream都有独立的滑动窗口,所以每个Stream都可以做流量控制,防止单个Stream消耗连接(Connection)的全部接收缓冲
接收窗口的左边界取决于接收到的最大偏移字节数
当图中的绿色部分数据超过最大接收窗口的一半后,最大接收窗口向右移动,接收窗口的右边界也向右扩展,同时给对端发送窗口更新顿,当发送方收到接收方的窗口更新顿后发送窗口的右边界也会往右扩展,以此达到窗口滑动的效果
限制连接中所有Stream相加起来的总字节数,防止发送方超过连接的缓冲容量
QUIC内部包含TLS1.3
QUIC协议没有用四元组的方式来“绑定”连接,而是通过连接ID来标记通信的两个端点,客户端和服务器可以各自选择一组ID来标记自己。因此即使移动设备的网络变化后,导致IP地址变化了,只要仍保有上下文信息(比如连接ID、TLS密钥等),就可以“无缝”地复用原连接