TCP
1 报文段结构

2 可靠数据传输原理
无比特差错信道的情况下:传输层天然传输可靠
只能保证数据无损坏,可传达,不保证有序。
有比特差错信道的情况下:数据可能存在比特差错。
-
因此首先接收方需要知道分组是否有错,即具备差错检测的能力。
-
其次,当接收方检测出分组存在错误时,需要告知发送方,即发送ACK与NAK。
-
最后,当发送方收到NAK时,发送方知道自己的分组存在错误。因此需要重传出错的分组。
但是,ACK与NAK分组也可能存在比特差错。发送方 面对出错的ACK或者NAK时,统一当成NAK处理,重传分组。这带来了一个新的问题:冗余数据分组,例如对于接收方而言。假设发出ACK的分组存在比特差错,而发送方重传分组。那么接收方会收到俩次同样的分组,接收方无法区分这是分组的重传还是新的分组。采用序号来解决冗余分组的问题
因为有了序号,所以NAK也就没有必要了。接收方对上一个分组的二次ACK,当成对当前分组的NAK。当发送方收到这种冗余ACK时,就知悉自己发送的分组出错。重传分组。
总结:引入了检验和,序号,冗余ACK,重传等技术
有比特差错与丢包的信道情况下
这时候发送方需要处理俩种问题
- 分组是否丢失
- 分组丢失后怎么办
计时器来判断分组是否丢失。分组丢失后重传分组。这同样带来了冗余分组的问题。用序号解决。
SR协议 窗口必须小于等于序号范围的一半
3 TCP如何实现可靠数据传输
TCP依赖的网络层IP不保证数据包的交付(即存在丢包), 不保证数据报的按序交付(即乱序),不保证数据报数据的完整性(即比特差错) TCP的可靠数据传输保证进程从其缓存中接收到的数据流是无损坏,无间隔,非冗余,有序的数据流。
确认机制,实现接收方对发送方的反馈。 定时器用于发送方实现检测丢包,冗余ACK的辅助检测丢包。 重传用于发送方处理分组比特出错,分组丢失的问题 序号用于解决冗余分组的问题。
窗口,流水线 用于提高性能 超时间隔加倍, 快速重传机制 收到3个冗余ACK,则视为丢包。重传报文
4 如何实现流量控制
维护接收窗口的变量,接受窗口代表接收方还有多少可用的缓存空间。
LastByteSent - LastByteACked <= rwnd
接受窗口的设置:通过TCP报文段首部的接收窗口字段。
当接收窗口为0时,发送方会不断发送一个1字节数据的报文段。否则,如果接收方没数据要发,也没ACK要发。导致即使接收方接收缓存清空,有内存接收数据了。无法告知发送方。导致发送方阻塞。
5 如何实现拥塞控制
TCP 采用端到端拥塞控制而不是网络辅助的拥塞控制,因为IP层不向端系统提供显式的网络拥塞反馈。
拥塞窗口变量(cwnd): LastByteSent-LastByteAcked <= min{cwnd, rwnd}
拥塞窗口限制了其传输速率,TCP利用确认增大拥塞窗口长度, 因此被说成是自计时的

- 慢启动
cwnd以一个MSS开始,每个RTT,cwnd翻番,即每个确认都将cwnd增加一个MSS。
如何结束?
1如果出现超时指示的丢包则将cwnd设置为1,ssthresh设置为cwnd/2并重新开始慢启动过程。2如果cwnd到达ssthresh,则结束慢启动进入拥塞避免模式,3如果检测到三个冗余ACK,则将cwnd减半+3个MSS,ssthresh设置为cwnd/2。执行快速重传并进入快速恢复状态。
- 拥塞避免
每个RTT只将cwnd的值增加一个MSS。即每一个确认,将cwnd增加 MSS/Cwnd 个MSS字节。
如何结束? 1如果超时,行为与慢启动时一样2.如果检测到三个冗余ACK,则将cwnd减半+3个MSS,ssthresh设置为cwnd/2。进入快速恢复模式
- 快速恢复(可选)
收到的每一个冗余ACK,cwnd增加一个MSS 如何结束? 当丢失报文段的ACK到达时,TCP将cwnd设置为ssthresh。进入拥塞避免 如果出现超时,同上
6 流量控制与拥塞控制
相同点:都是用于遏制发送方发送速率
不同点:原因不同,流量控制是为了实现发送方的发送速率与接收方的应用程序读取速率匹配,防止接收方接受缓存溢出。 拥塞控制是因为网络堵塞,如果不遏制速度,会加剧堵塞导致丢包越来越多。
7 TCP连接的建立与拆除
三次握手
- 客户发送一个特殊的报文段,SYN置为1,同时该报文段携带了一个ISN
- 服务器收到该报文段,为该连接分配TCP缓存与变量,向客户发送ACK,同时SYN置为1,该报文段携带了一个ISN
- 客户收到该报文段,客户发送ACK。SYN置为0。
为什么需要三次握手而不是四次,二次?
三次握手的目的是约定双方的ISN,约定一方的ISN需要2次握手。而服务器对客户端的ISN 的ACK 以及自己的ISN 合并在一起。因此不是四次握手而是三次。
为什么需要ISN(序列号) ?
序号用于解决冗余分组的问题,来区分这个分组是新的分组还是重传。另外连接复用时,序号也可以帮助区分这个分组是否是旧连接的分组。
TCP缓存与变量是什么?
缓存就是字面意思。缓存收到的数据,等待进程提取。缓存待发送的数据,等待TCP发送
变量有:接收窗口,发送窗口,lastbyteSent, lastByteAcked,
四次挥手
- 客户发送特殊报文段,FYN置为1
- 服务器收到该报文段,发送ACK。服务器进入close_wait状态
- 服务器数据发送完毕后,发送特殊报文段,FYN置为1,进入last_ack状态
- 客户收到该报文段,发送ACK,进入time_wait状态,等待2ms后,客户进入closed状态
为什么要4次而不是3次
因为需要2次挥手才能完成一方的连接关闭,而服务器确认客户端的挥手时,可能还有数据要发,因此服务器的FIN与 ACK是分开发送。于是是四次挥手而不是三次。
画出客户TCP连接建立与拆除的状态序列

上图中time_wait阶段的意义
- 当ACK 丢失,time_wait使得客户重传最后的确认报文
- 防止新的连接收到前一个连接延迟的数据包(恰好新旧连接同一个端口)
画出服务器TCP连接建立于拆除的状态序列

客户向服务器发送了端口XX的连接,该连接一定会建立吗
不会,需要服务器在xx端口接收连接(即套接字处于listen状态)。如果不接收连接,服务器会发送一个特殊重置报文段
nmap端口扫描工具原理
向服务器XX端口发送SYN报文段,可能得到如下回应
- 收到SYN ACK报文段,说明服务器打开了XX端口
- 收到RST报文段,说明报文段到达了服务器,但是服务器没有运行指定端口的应用程序
- 什么也没收到,说明报文段可能被中间防火墙阻挡,没有到达服务
SYN 泛洪攻击
发送SYN,而不完成第三次握手来耗尽服务器资源
解决办法:
TCP与UDP的不同
- 面向连接与无连接,维护连接状态与不维护连接状态
- TCP需要维护连接状态。UDP没有
- 首部开销
- TCP拥塞控制流量控制,UDP没有
- TCP点对点,UDP可以一对多,多对一,多对多
UDP
UDP在网络层之上只添加了最基本的复用/分解 以及校验和服务。
为什么UDP要提供校验和
- 不能保证源和目的之间的所有链路都提供差错检测
- 报文段在路由器内存中时,可能引入差错
报文段结构

Ref
- 计算机网络自顶向下方法
- zhuanlan.zhihu.com/p/40013724