重要概念
标记位:
URG:紧急指针有效
ACK:确认序号有效
PSH:接收方应该尽快将这个报文交给应用层
RST:重置连接
SYN:发起一个新连接
FIN:释放一个连接
序号Seq: 用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记
确认号Ack: 标记位为ACK的时候用于确定需要有效,Ack=Seq+1
三次握手-TCP连接的建立
1、进行三次握手前,客户端结束CLOSED状态,服务端结束CLOSED状态,转为LISTEN状态
2、客户端结束CLOSED状态后,向服务端发送TCP报文:
标记位:SYN
序号:Seq = x
发送报文后客户端状态变为SYN-SENT
3、服务端接收到TCP报文,确认无误后返回一段TCP报文:
标记位:SYN ACK
序号:Seq = y
确认号:Ack = x + 1
之后服务端进入SYN-RCVD状态
4、客户端接收到确认的TCP报文,确认无误后说明客户端知晓了和服务端之间的连接是无误的,随后发送一段TCP报文:
标记位:ACK
序号:Seq = x + 1
确认号:Ack = y + 1
之后客户端状态变为ESTABLISHED
5、服务端再次接收到来自客户端的TCP报文,也知晓了两者之间的连接是正常的,也将状态变为了ESTABLISHED
四次挥手-TCP连接的释放
1、客户端主动申请断开连接,结束了ESTABLISHED状态,发送TCP报文:
标记位:FIN
序号:Seq = x
之后客户端进入FIN-WAIT-1状态,这个状态下客户端停止向服务端发送数据(仍可发送报文),可接收从服务端传输过来的数据。
2、服务端收到请求释放的报文,结束ESTABLISHED状态,发送确认的TCP报文:
标记位:ACK
序号:Seq = y
确认号:Ack = x + 1
之后服务端进入CLOSE-WAIT状态,客户端收到该TCP报文并进入FIN-WAIT-2状态
3、服务端在CLOSE-WAIT状态下通知应用进程释放资源,还可能继续给客户端发送一些数据,进程处理完相关资源后,表示可以断开,再次发送TCP报文:
标记位:FIN ACK
序号:Seq = z
确认号:Ack = x + 1 (和第二步的确认号相同)
之后服务端结束CLOSE-WAIT状态进入LAST-ACK状态,在这个状态下服务端停止向客户端发送数据(仍可发送报文),可接收从客户端传输过来的数据。
4、客户端收到TCP报文,确认了服务端已经做好了断开连接的准备了,再次发送TCP报文:
标记位:ACK
序号:Seq = x + 1
确认号:Ack = z + 1,
服务端接收到该TCP报文后,进入CLOSE状态
客户端在发送该报文后进入TIME-WAIT状态,在此状态下等待2MSL(MSL:TCP报文在传输过程中的最大生命周期)后结束TIME-WAIT状态,进入CLOSE状态
为什么在TIME-WAIT状态要等待2MSL?
如果客户端在2MSL内,再次收到服务器端发送的FIN报文,说明服务器端没有接收到客户端发出的ACK报文。于是,客户端再次向服务器端发出ACK报文,并且计时器重置。
服务端某个程序,需要通信(new socket),首先调用内核的传输控制层,传输控制层准备了第一个握手的包,然后在这里阻塞,然后调用网络层进行路由寻址,找到下一跳的ip地址,然后找链路层寻找mac地址,网络层和链路层的一系列信息会封装进刚才的包,这样包才能发出去。