TCP的三次握手
TCP头中有以下几种状态位:
状态位 | 描述 |
---|---|
SYN | 发起一个连接 |
ACK | 响应、确定 |
PSH | 表示有数据传输 |
FIN | 结束连接 |
RST | 重新连接 |
URG | 紧急指针字段值有效 |
-
TCP的连接建立,我们常常称为三次握手。
其实就是一个请求、应答、再应答的过程。就跟我们平常不知道信号好不好的时候打电话一样,通常都会有这么一个场景:
A:你好,我是A,请问你听得到我讲话吗。
B:你好,我是B,我听得到你讲话,你听得到我讲话吗。
A:嗯嗯,我听得到。
然后A和B两个人就开始正常的交流。其实TCP的连接建立也是这么三个回合。 -
为什么是三次握手,而不是两次呢?
还是拿上面那个例子说明,假设我们只要2个回合就建立连接,当B说完第二句的时候就开始掏出纸和笔准备记录A要交代他的事情。因为他认为此时连接已经建立好了,但是此时A由于信号太差却听不到B说的第二句话,然后因为迟迟没有收到B的回话,把电话挂了,但是B却不知道(挂电话没有嘟嘟嘟的提示声),还在傻乎乎的等着A交代事情,这不就是浪费B的时间和精力吗。 -
那为什么不是四次握手呢,万一要是B没收到A的回复,然后把电话挂了(挂电话还是没有嘟嘟嘟的提示声),A岂不是傻傻的一直在自言自语吗?
那照这样说的话,其实4次握手也可以,400次握手也可以,甚至你想,可以一直握下去,打电话也就变成了两个人一直在问对方你听得到吗?你听得到吗?但是这样永远也不能保证对方相互可靠。所有只要消息有一次来回,就认为连接已经建立了。就比如A收到B的回复就认为连接已经建立了,B收到A的回复就认为连接已经建立了。这里说明下A是客户端,B是服务器端。 -
TCP包的序号的问题
双方在建立连接的过程中还会商量TCP包的序号的问题。A发送SYN的时候,会告诉B,A这边的序号是从哪号开始的,B的ACK的确认序号就是A告知的序号加一,同理B也是如此。假如每次建立连接,TCP包的序号都从1开始的话,A和B建立连接以后,连续发了1、2、3 三个包,但是3号包一直没有被B接收到,然后此时A突然掉线了,重连上B以后,序号又从1开始,只发送1、2 两个包,但是此时之前发送的3号包又被B接收到了,B自然会认为这是下一个包,于是就发生了错误。所有,每个连接都要有不同的序号,这个序号的起始序号是随时间变化的,可以看成是一个32位的计数器,每4ms加一。4个多小时才会出现重复,那个一直没被接收的包早就失效了。 -
状态时序图
-
流程
一开始的时候,客户端和服务器端都处于CLOSED状态,服务器先会主动监听某个端口,处于LISTEN状态,然后此时客户端会主动发送一个SYN给服务器,请求建立连接,随后就一直处于SYN-SENT状态,服务器在接收到客户端的请求之后,也会发送一个SYN,请求建立连接,并且发送一个ACK回复客户端的SYN。随后处于SYN-RCVD状态,客服端接收到服务器端发送的请求和回复之后,也会回复一个ACK给服务器端,随后进入ESTABLISHED状态,最后服务器端接收到客户端的回复后,也进入了ESTABLISHED状态。
TCP的四次挥手
当A和B需要断开连接的时候也有一个流程,这个流程有4个回合,也被我们称为4次挥手。
- 状态时序图
- 流程
首先客户端和服务器端都处于ESTABLISHED状态。当客户端想断开连接的时候,会发送一个FIN请求给服务器端,请求断开连接。随后进入FIN-WAIT-1状态,当服务器端接收到客户端的请求时,会回复ACK给客户端,随后进入CLOSED-WAIT状态,过一段时间后,再发送一个FIN请求给客户端,请求断开连接。随后进入LAST-ACK状态,当客户端收到服务器端的请求时,也会回复一个ACK给服务器端。随后进入TIME-WAIT状态,并且会在2MSL(MSL是报文最大生存时间)后进入CLOSED状态当服务器端接收到客户端的回复后,就会直接进入关闭状态。
TCP状态机
其中阿拉伯数字的序号,是连接过程中的顺序,而大写中文数字的序号,是断开连接过程中的顺序。加粗的实线是客户端A的状态变化,加粗的虚线是服务器端B的状态变迁。