选择重传与分片的概念
选择重传不是指分片中的某个部分丢了,选择某个分片
选择重传的粒度不是分片而是滑动窗口中的单元
TCP协议中的seq表示的是字节数还是包序号?
seq其实就是连接的字节数
TCP中发送数据后,基本就是已经异步过程了,应用程序没有办法掌控
数据仅仅是拷贝到了发送队列中,之后的数据发送就是交给ip层了,需要做路由选择
数据发送tcp_sendmsg中间还是需要判断滑动窗口、拥塞窗口、nagle判断
后续的数据发送只能靠Peer的回包的反馈来驱动滑动窗口将队列中的数据吐出去
应用层还有一种可能通过SO_PRIORITY来优先级发送
TCP传输特性
时序性、通道利用率、可靠性
TCP与IP层的矛盾
从Tcp的收发包的过程和滑动窗口协议来看,Tcp依赖的是很远地方的Peer给的信息来调整队列中的数据发送
Tcp实际上使用两个端点的信息来评估网络的拥塞程度,理论上不可能准确
但是IP层却能知道整个链路的拥塞程度,这种学习的信息不能够分享给tcp的两端
IP层的网络很多节点是公共资源,只有处在两端的设施是个人或者企业私有的
Tcp Recv flags 特性
MSG_TRUNK 表示不要管len这个用户态内存有多大,只管拷贝数据
MSG_WAITALL 读取到len长度的消息才能返回
MSG_PEEK 主要用于多进程读取同一套接字的情形
SO_RCVLOWAT receive队列为空了,此时会先来检查SO_RCVLOWAT这个阀值。
如果已经拷贝的字节数到现在还小于它,那么可能导致进程会休眠,等待拷贝更多的数据。
SO_RCVTIMEO recv方法传入的len参数,是表示必须超时(SO_RCVTIMEO)或者接收到len长度的消息,就会返回
阻塞方式的最长等待时间为SO_RCVTIMEO指定的时间
TCP接受数据拥有多个队列
receive queue 已经排好序的数据的队列
prequeue 在进程睡眠等待的时候,新的数据包到达后,数据放到prequeue中
backlog 进程正在拷贝数据时,网卡收到的报文会进这个队列。此时若backlog队列有数据,就顺带处理下。
out_of_order 乱序达到的数据包的队列,网卡收包的时候顺便检查out_of_order,将buffer从中移除,tcp_ofo_queue
SYN-COOKIE
避免内存被分配光
难道是收到的包时分配的skb_buffer导致的内存被用光吗
网卡驱动中的内存分配应该是一开始分配一定数量的的skb_buffer,然后当数据包在中断下半部的时候,从queue中取走放到协议栈的recv queue的时候,
这个skb_buffer的数量可能需要一定的补充
这个内存被用光是指TCB的控制块的内存用完
当开放了一个TCP端口后,该端口就处于Listening状态,不停地监视发到该端口的Syn报文,一旦接收到Client发来的Syn报文,
就需要为该请求分配一个TCB,通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至需要1300个字节,并返回一个SYN ACK命令,
立即转为SYN-RECEIVED即半开连接状态,而某些操作系统在SOCK的实现上最多可开启512个半开连接
对于SYN攻击,Syn cookie为了判断后续对方发来的ACK报文中的SequenceNumber的正确性
完全不使用任何存储资源,这种方法比较巧妙,它使用一种特殊的算法生成SequenceNumber,
这种算法考虑到了对方的IP、端口、己方IP、端口的固定信息,以及对方无法知道而己方比较固定的一些信息,
如MSS、时间等,在收到对方的ACK报文后,重新计算一遍,
看其是否与对方回应报文中的(Sequence Number-1)相同,从而决定是否分配TCB资源
使用SIMD指令集来提高算法的运行效率
类似http中的ssl加速
SACK
SACK是TCP选项,它使得接收方能告诉发送方哪些报文段丢失,哪些报文段重传了,哪些报文段已经提前收到等信息。
根据这些信息TCP就可以只重传哪些真正丢失的报文段。
需要注意的是只有收到失序的分组时才会可能会发送SACK,TCP的ACK还是建立在累积确认的基础上的。
也就是说如果收到的报文段与期望收到的报文段的序号相同就会发送累积的ACK,SACK只是针对失序到达的报文段的。
SACK包括了两个TCP选项,一个选项用于标识是否支持SACK,是在TCP连接建立时时发送;另一种选项则包含了具体的SACK信息
拥塞控制算法
这是一个信号反馈的算法
捕获突发,一旦超过了一次最大发送包(Burst),拥塞窗口就会减少
捕获反馈(ack),拥塞窗口增加,增加的是1或者2*N个MSS
窗口大于ssthresh就进入拥塞避免
小于ssthresh就进入慢启动
发生丢包后,sshthresh=窗口/2
ssthresh的物理意义就是带宽
流量整形与Burst
突发导致的数据发送端的流量曲线有毛刺
RTT与RTO
RTO的初始值是3*RTT
RTO是每个链接维护一个,并不是每个包维护一个
RTO最小200ms,最大时间120s
in flight与Qdisc
已经乱序,但是未丢失的字节数,在路上的数据包
处在飞行状态,还未落地
当前已经发送的-已经被确认的
tcp协议栈 in-flight = tcpdump in-flight(网卡) + Qdisc
数据包从ip层投入到了Qdisc后,怎么触发数据到网卡的DMA ring中
ICMP在tcp中的存在性
在connect服务器时,如果收到了icmp的不可达的数据包
则返回EUNREACH错误码
发送窗口、通告窗口、拥塞窗口(CongestionWND)
发送窗口=min(aknowledge window,cwnd)
收发一致性, 收到多少个ACK包,就发送多少数据出去
拥塞窗口就是包的个数,不是字节数
当前的cwnd等于在网路中的in_flight+当前可以发送的数据
tosend等于当前被ACK的数量,表示将要发送的数据包
如果cwnd等于in flight的话,就表示不能再发送了
MSS协商与MTU
三次握手过程中就会携带MSS
TSO、GSO、UFO、GRO
TSO (TcpSegmentation offload)
GSO (genericsegmentation offload)
UFO (UDPfragmentation offload)
GRO(genericreceive offload)
主要是利用网卡的分片和合并分片的功能(scatter,gather),降低协议栈负担
这些分包与合并包在网卡的驱动程序中会有体现
Delay Ack
接收端,可以一次发送对多个包的确认
不是每一次都只发一个,相当于打包多个ack发送
另外就是Ack与数据一起发送
多少路径会发送RST
1、 目的端上并没有监听端口,取收到了SYN
2、 收到根本不存在的连接上的数据包
3、 关闭连接(最大连接限制,但3次握手正常)
4、linger选项会改变close的行为,从FIN改变为RST
数据包接收的Fast Path与Slow Path
下面的场景采用慢速路径来处理接收包
A zero window was announced from us - zero window probing is only handled properly in the slow path.Out of order segments arrived.
Urgent data is expected.
There is no buffer space left
Unexpected TCP flags/window values/header lengths are received (detected by checking the TCP header against pred_flags)
Data is sent in both directions. Fast path only supports pure senders or pure receivers (this means either the sequence number or the ack value must stay constant)
Unexpected TCP option.
Push选项的含义
在接收方收到Push的标记时,表示将当次收到的数据与缓存中已有的数据一起提交给进程,表示完整性
Cork选项的含义
避免发送大量的小包