【计算机网络复习】TCP简单入门
/ / 点击 / 阅读耗时 12 分钟TCP 的优点
与UDP相比,TCP可靠、面向连接。她有如下的一些特点:
- 面向连接;
- 是点到点的;
- 提供可靠的交付服务,并且传送的数据无差错、不丢失、不重复并且有序;
- 全双工(双方都需要维护发送以及接受缓存);
- 面向字节流的(seq,ack都是针对字节流的)
TCP报文
1 | TCP Header Format |
具体的阐述参见:RFC TCP。
与UDP相同的是,TCP的校验也采用伪首部,具体细节同样参见RFC 793。
options可以用于确定MSS大小,最终取双方中较小值。
TCP连接的建立
TCP连接需要来回发送一共三条报文,也就是大名鼎鼎的“三次握手”。
1 | TCP A TCP B |
首先,TCP A发送一条报文(进入SYN-SENT状态),其中SYN位置1,表示这是一条请求TCP连接建立的报文;
其次,当TCP B接受到SYN位置1的报文时(进入SYN-RECEIVED状态),它发送一条SYN,ACK位均置1的报文,其中报文的ack号是接收到的报文seq加一(需要注意的是,上图2中的报文是没有携带任何数据的,但是依然需要消耗一个序列号!);
最后,接收到TCP B发送报文的TCP A进入ESTABLISHED状态,并发送一条只有ACK置1的报文(这一条报文可以携带数据),表示连接建立成功。
为什么需要三次握手?
概括一下,三次握手可以防止old deplicated syn,避免服务器的资源空耗,统一双方的seq以及ack。
TCP连接的释放
1 | TCP A TCP B |
1.数据传输结束后,客户端的应用进程发出连接释放报文段,并停止发送数据,客户端进入FIN_WAIT_1状态,此时客户端依然可以接收服务器发送来的数据。
2.服务器接收到FIN后,发送一个ACK给客户端,确认序号为收到的序号+1,服务器进入CLOSE_WAIT状态。客户端收到后进入FIN_WAIT_2状态。
3.当服务器没有数据要发送时,服务器发送一个FIN报文,此时服务器进入LAST_ACK状态,等待客户端的确认
4.客户端收到服务器的FIN报文后,给服务器发送一个ACK报文,确认序列号为收到的序号+1。此时客户端进入TIME_WAIT状态,等待2MSL(MSL:报文段最大生存时间),然后关闭连接。
四次挥手的原因
四次挥手的原因:由于连接的关闭控制权在应用层,所以被动关闭的一方在接收到FIN包时,TCP协议栈会直接发送一个ACK确认包,优先关闭一端的通信。然后通知应用层,由应用层决定什么时候发送FIN包。应用层可以使用系统调用函数read==0来判断对端是否关闭连接。
可靠传输机制
序号
TCP为字节流维护序号,确保了数据在传递时的有序性
确认
TCP报文中指出希望对方发送的下一个报文的序号,并使用累计确认机制。该机制可以用于及时发现哪些报文丢失,及时重传
重传
在两种情况下重传:1. 报文段的计时器超时;2. 收到了冗余ACK
流量控制
着眼于点到点,确保连接双方的速率匹配,接收方通过TCP 报文中的rwnd字段来告诉发送方它还有多大的接受缓冲空间。
拥塞控制
着眼于网络全局,通过拥塞控制算法,TCP估计当前网络负载能力,计算出cwnd,最终发送方发送的报文大小取cwnd以及rwnd中的较小值。
拥塞控制算法v1:
设置ssthresh;
设置cwnd=1;
- 进入指数增长阶段,每一个RTT,将cwnd翻倍(另一种表述:每接受到一个ack,cwnd++);如果发现2*cwnd > ssthresh,令cwnd=ssthresh,进入3;如果出现网络拥堵(报文超时),那么将ssthresh = cwnd/2(至少为2),然后进入1;
- 进入加性增阶段,每一个RTT,cwnd++;如果出现网络拥堵(报文超时),那么将ssthresh = cwnd/2(至少为2),然后进入1;
算法v1存在一些问题:很多时候我们很难及时察觉出网络的阻塞。为此,我们引入快重传以及快恢复方法:
- 快重传:如果收到某一个报文的连续3次ack,那么重传对应序号报文;
- 快恢复:如果收到某一个报文的连续3次ack,那么设置ssthresh = cwnd/2,cwnd=ssthresh
一些细节问题
TCP 中的滑动窗口机制
可以看出,在使用滑动窗口机制下,即使一些ack没有成功收到,也有可能不会导致重发,因为之后的ack一旦收到,之前的所有报文也都一定被收到。
流量控制中的探测
如前文所述,流量控制中的窗口大小是通过接收方的报文通知发送方的,因此,如果发送方在以为接收方没有任何缓冲区空间之后,接收方通知有新的缓冲区空间报文丢失,就会导致发送方“饥饿”。为此,发送方会在一个RTO之后尝试发送一个报文,通过接收方的ACK探测当前是否有新的缓冲区空间。
拥塞控制中的ssthresh
《图解TCP/IP》中指出,TCP通信的开始不会直接指出ssthresh的值,而是在第一次网络拥塞之后计算出。
快恢复的cwnd
《图解TCP/IP》中的说法是ssthresh+3,加3 的原因是因为收到3个重复的ACK。