TCP的三次握手
TCP三次握手过程
假设有一个发送方计算机和一个接收方计算机,纵向为时间轴
第一次握手
假设首先是发送方主动和接收方建立连接,所以,发送方会第一次发送一个报文(此时SYN=1,表示这是一个连接请求的报文,seq=x是同步发送方自己的序列号)
第二次握手
接收方在接收到连接请求后,也就打开TCP连接,同时它也会发送一个报文,这个报文是第二次握手。报文信息中有:
- SYN=1:表示是一个连接请求
- ACK=1:表示对序列号的确认
- ack=x+1:小写的ack表示的是确认号。这里的ack=x+1,表示接受方期望收到的是x+1这个序列号的值
- seq=y:同时接收方发送的报文中也会携带自己的序列号,也就是seq=y
第三次握手
发送方接收到报文之后,会进行回应,回应中的报文内容:
- ACK=1:表示这个报文的确认号是有效的
- seq=x+1:发送方所携带的序列号,表示的是,当前发送方发送的数据序列号是x+1
- ack=y+1:确认号是y+1,表示发送方期望接收到接收方的序列号是y+1的数据
通过这三次的握手,TCP的连接就建立起来了
三次握手中关键的信息
- 第一次和第二次握手都有SYN标记,表示这是一个连接的请求
- 第二次和第三次握手都有ack标记,对于ack这个标记,它其实是先对连接双方的序列号进行同步。比如说,通过两次的ack同步,发送方已经知道了接收方的ack是什么了,同时,接收方也知道了发送方的ack是什么了,通过三次握手,它们不仅仅将连接建立起来,并且也同步了各自的序号
在三次握手的时间轴中,不同的时间,接收方和发送方有不同的状态
- 在接收方没有接收到数据之前,它一直处于监听状态(Listen)
- 发送方在第一个报文发送出去,到接收到第一个报文的响应之间,属于同步已发送状态(SYNC-SENT),表示已经将SYN发送出去了,并且等待对方的SYN信息
- 从接收方发送第一个报文,到接收到第二个报文之间,属于同步已接收状态(SYNC-RCVD),表示发送方发送给我的SYN信息,我已经收到了
- 然后发送方就进入建立连接(ESTABLISHED)的状态了
- 对发送方来说,只要第二次握手成功之后,发送方就建立起连接了。但是对接收方来说,只有接收到发送方的第三次握手之后,才是建立连接的状态(ESTABLISHED)
双方对于建立连接状态的时间是不一样的,发送方只要在第二次握手成功之后,就变成了建立连接的状态。但是对接收方来说,只有接收到发送方的第三次握手之后,才是建立连接的状态。双方都进入建立连接的状态之后就可以进行数据的传输了
为什么发送方要发出第三个确认报文呢?为什么两次不行?
结论:避免已经失效的连接请求报文传送到对方,引起错误
假设此时有一个发送方计算机和一个接收方计算机。首先发送方需要发送一个建立连接的请求报文(第一次握手),假设第一次握手的报文在网络中传输很久才到达接收方,因为发送了很久,所以,发送方很久都没有收到接收方的确认消息。发送方就会认为第一个报文已经超时了,所以,发送方就会第二次发送同样的报文
假设第二次发送的报文,很快就到达了对方,接收方在收到第二次的连接请求报文之后,就会进行回应,并且建立起它们之间的连接。那么,对于发送方发送的第一次的请求报文,就应该是一个失效的请求报文,因为它的功能已经被第二次的连接请求所完成了。所以,对于第一次发送的请求连接报文,在网络中游荡了很久,其实就是一个失效的请求报文了,没有作用了
如果发送方发送的两次连接请求都建立起连接了会怎么样?
首先考虑第二次请求的报文,这个报文是提前到达接收方的,接收方会对它进行一个回应,回应确认之后,就建立起连接了(因为我们是假设两次握手就建立起连接)
现在考虑第一次发送的连接请求,如果两次握手就建立连接的话,对于失效的请求,它也会建立起连接,因为只要接收方回应了,就表示连接已经建立了
这样就会导致,同样的请求发送了两次,就会建立两个TCP连接的情况。这种情况是错误的,所以说,两次握手是不正确的
三次握手是如何解决两次握手导致的问题?
对于两次握手,只要接收方回应了,就表示连接建立了。而对于三次握手来说,第一个确认报文会首先到达发送方,然后发送方再发送一个确认报文(第三次握手),此时才算建立起连接
现在来考虑那个比较慢到达接收方的连接请求报文,这个报文,接收方也会发送一个确认报文给发送方(第二次握手)。但是发送方已经进行第三次握手了,因此发送方对于第二次的确认消息会忽略掉,并不会进行任何的操作。这样,第一次比较慢到达的连接请求就不会建立起连接,这就避免了两次握手所导致的错误
TCP的四次挥手
TCP四次挥手过程
还是假设这里有一个发送方结算机和一个接收方计算机,纵向为时间轴。连接正常的时候,双方是可以一直进行数据传输的。假设数据传输完成了,此时就会进行TCP连接的释放。假设发送方主动的进行了连接的释放
第一次挥手
发送方发送第一次挥手的报文,报文内容:
FIN=1:该标记表示需要释放连接
seq=u:同步自己的序列号给接收方
此时发送方就进入了连接结束的第一个等待状态(FIN-WAIT-1)
第二次挥手
接收方在收到发送方的断开连接请求之后,它也会发送一个报文去确认,确认对方给我发送的序列号我已经收到了,确认报文内容是:
ACK=1:表示这个报文已经确认
seq=v:同步自身的序列号
ack=u+1:确认号是u+1,表示接收方期望接收到接发送方的序列号是u+1的数据
发送方接收到确认报文之后,就进入了连接结束的第二个等待状态(FIN-WAIT-2)。而接收方在发送了第一个确认报文之后就进入了关闭等待状态(CLOSE-WAIT)
这个时候其实接收方还是可以进行数据的发送的,因为释放连接的请求是发送方发起的,表示说发送方的数据发送完成了,但是接收方可能还没有发送完成
第三次挥手
接收方发送完第一个确认报文之后,又会发送一个新的报文,这个报文会携带FIN=1的标记,表示它也可以进行连接释放了,并且里边会携带一个ack,表示重复的对发送方发送的序列号进行确认,该报文中的完整内容:
FIN=1:该标记表示需要释放连接,是一个释放连接的请求
ACK=1:表示确认报文已经收到
seq=w:给发送方同步自己的序列号
ack=u+1:确认号是u+1,表示接收方期望接收到接发送方的序列号是u+1的数据
第四次挥手
发送方接收到接收方的确认报文之后,又会发送一个确认报文,确认接收方发送的报文我已经收到了,此时可以释放掉连接了
在接收方发送断开连接的请求到发送方的确认报文被接收方收到这之间,接收方处于最后确认状态(LAST-ACK)。是为了确认发送方已经接收到了连接释放的报文,此时发送方进入了等待计时器状态(TIME-WAIT)。发送方会在这个时间等待状态中等待一段时间,确保这段时间没有出现任何的问题,此时才进入关闭状态(CLOSE)
以上便是四次挥手的过程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。