TCP 是一种面向连接的网络层传输协议,它建立在不可靠的 IP 层之上,向上层应用层提供可靠的传输服务。
它是面向字节流的传输。
TCP 报文头部:

可靠传输
其可靠传输主要依赖于以下几方面实现:校验和、序列号和确认序号、三次握手建立连接、超时重传、流量控制、拥塞控制。
三次握手
- 客户端 发送建立连接请求,设置
SYN=1, 初始化序列号seq=x,发送请求连接报文给 服务端,然后客户端 进入SYN_SENT状态,等待服务器确定。 - 服务端 接收到 客户端 的
SYN报文,对该报文进行确认,设置ACK=1。 同时还要发送自己的 SYN 报文,设置SYN=1, seq=y, 将确认报文和 SYN 报文合并到同一个报文中,发送给 客户端, 此时 服务端 进入SYN_RECV状态。 - 客户端 收到 服务端 的
SYN_ACK报文后,向sever发送ACK报文,将ACK=1,发送给服务端, 服务端接收到报文后,都进入建立状态,完成三次握手。

四次挥手
TCP断开连接都由用户请求。
- 客户端 发送数据完成后,向服务端发送释放连接报文,报文 FIN=1, 发送后,客户端只能接受数据,不能发送。客户端进入
FIN_WAIT_1状态。 - 服务端收到释放连接报文后,向客户端发送 ACK 报文,报文 ACK=1。此时服务端能向客户端单向传输数据。进入
CLOSE_WAIT状态。客户端收到后,进入FIN_WAIT_2状态。 - 客户端完成数据发送后,向客户端发送释放连接报文, 报文 FIN=1, ACK=1。 进入
LAST_ACK状态。 - 客户端收到释放连接报文后,向服务端发送 ACK 报文,报文 ACK=1。进入
TIME_WAIT状态。等待两个 MSL 长度后,关闭连接。

连接相关问题:
为什么不能两次握手?
三次握手是为了保证双方都能确认自己和对方都能正常的发送和接收。考虑丢失,如果第二个报文丢失,则客户端认为还没有建立连接,而在服务端看来已经正常建立连接,这样会浪费服务端的资源。
为什么关闭四次
因为要确保双方都能通知对方释放连接。第一次是断开客户端到服务端的单向连接,而此时服务端可能还没发送完所有数据,还要继续发送。当服务端发送完成后,再通知客户端断开连接。同时每一次释放连接的报文都需要分别收到对方的确认报文。其实是,在建立连接时,服务端的 ACK 和 SYN 都在第二次的握手过程中一次性完成了,而在断开连接时,则要先传 ACK, 等自己发送完成后才能传 SYN。所以需要四次。
为什么 需要等待 2MSL
可以使每次 TCP 连接的报文全部消失,不会出现在下一次的 TCP 连接中。
如果第四次握手信息丢失,则服务端无法收到客户端的确认信息,就需要重发第三次握手的报文。如果此时客户端已关闭,则会导致服务端无法正常关闭。
SYN flood 攻击
如果恶意地向某个服务器端口发送大量的SYN包而并不完成建立连接的全过程,则可以使服务器打开大量的半开连接,从而消耗大量的服务器资源,同时也使得正常的连接请求无法被相应。
流量控制
什么情况下需要流量控制?
流量控制是为了避免接收方缓冲区溢出造成的丢包。如果发送端发送的数据过快,接收端来不及接收就会出现丢包,这时就要用到流量控制,避免因接收端缓冲区溢出的丢包。
如图所示,在TCP首部有一个窗口大小字段,表示当前接收端缓冲区的大小。每当接收端发送ACK报文时,会将窗口大小填入其中,发送方会根据窗口大小调整发送速度。当窗口大小为0, 发送方会停止发送数据。
流量控制出现死锁怎么办?
发送方在接收到一个窗口大小为0的ACK报文后,发送方便停止发送,等待下一个ACK。但是如果下一个ACK丢失,则发送方就会一直等待下去,而接收方会认为发送方已经收到该ACK,等待新数据,便会产生死锁。
为避免死锁的发生,TCP采用计时器,当接收到一个零窗口的ACK后便启动计时器,一旦到达计时器的实践便主动询问接收方窗口大小,如果仍返回零则继续等待,若窗口不为零则开始发送。
拥塞控制
什么时候需要拥塞控制
拥塞控制是为了避免网络状况拥塞造成的丢包。 注意其与流量控制的作用的不同之处。
拥塞控制方法
拥塞控制方法主要包括:慢启动、拥塞避免。快速重传。快速恢复。
慢启动
发送方维持一个叫做拥塞窗口
cwnd的变量,取决于网络的拥塞程度,并在不断变化。注意由于可能存在接收方的流量控制的缓冲区窗口,所以发送方的真正的发送窗口可能小于拥塞窗口。慢启动的思想就是不要一开就发送大量数据,而是不断增加发送的数据的大小,不断试探一下网络的拥塞程度。
在慢启动中
cwnd的每次加倍拥塞避免
当拥塞窗口
cwnd增加到一定程度超过门限值ssthresh后,再每次倍增则风险太高。这时就进入慢启动阶段在拥塞避免中
cwnd每次增加一当判断网络出现拥塞(根据没能按时收到
ACK)则开始把拥塞避免的门限ssthresh变为出现拥塞时发送窗口的一半。并将拥塞窗口置为一,重新进入慢启动。快速重传
若接收方连续收到三个重复确认则立即重传对方尚未接收到的报文段,而不必继续等待计时器时间到期。(因为这表明是发生了丢包,而不是网络延迟大)
快速恢复
在拥塞避免时,一旦发送拥塞则
cwnd重置为慢启动阶段,为提高性能则把cwnd设置为ssthresh减半后的值,而不是重新从头开始进入慢启动。
总结
注意到流量控制会存在一个流量控制窗口,而拥塞控制中同样存在一个拥塞控制窗口,因此在实际传输时,TCP 传输窗口的大小取决于这两个值的最小值。