聊聊TCP三次握手和四次挥手

来源:互联网 发布:shadowsockx for mac 编辑:程序博客网 时间:2024/04/30 05:04
最近在了解一些TCP协议的东西,在此记录一些自己的体会和思考。

1.TCP

首先呢,TCP是一个传输层协议,顾名思义就是在应用层下面搬砖的啦。上层比如我们web应用常用的HTTP,流媒体应用常用的RTMP,会在TCP之上进行数据的收发工作。
TCP是一个面向连接的服务,所谓面向连接呢,是相对于UDP这种无连接服务而言的。无连接服务好比自动售货机,投币给货,使用方便,但是不稳定,会丢(数据)东西,售货机也不知道货物到底有没有被买家安全完整取走。而面向连接的服务呢,就像两个商人面对面做生意,咱俩先各自做做背景调查,看看双方(网络通不通)靠不靠谱,如果双方都靠谱,那么彼此之前就搭起了一座友谊的桥梁,然后就在此基础上该干嘛干嘛。我们一般把这个闷骚的过程叫做“三次握手”。
来,TCP又是一个全双工的服务,这个名词听着有点高冷哟。所谓全双工,我们还是拿刚刚那个例子,你用自动售货机的时候,你只能从售货机买东西而不能卖东西给它吧。而两个商人做生意,互通有无很正常吧。对嘛,全双工就是指TCP连接建立后,数据可以从A流向B,也可以从B流向A。

2. TCP三次握手

好,下面我们聊一聊三次握手。
一个TCP发送包的首部为:16bit 源端口号,16bit 目的端口号(用以多路复用多路分解来自或送到上层应用的数据), 32 位序列号(该包的编号),32位确认序列号(用以接收方回信时的序号)其他的6比特标志位:确认位ACK,推送位PSH,同部位SYN,终止位FIN 。
握手过程我们来看个图(注意客户机和服务器各自的状态变化):


上图所示
第一次握手:客户端TCP首先将SYN同步序列号置为1,再随机选择一个初始序号(client_isn)并将其放置于起始的TCP SYN报文段的序号字段中(seq)。
其实就相当于商人打招呼,告诉对方自己的一些相关信息,顺便提供一些鉴权的手段(比如适当地随机化选择client_isn)
第二次握手:一旦包含TCP SYN报文段的IP数据报到达服务器主机,服务器首先会提取客户数据报中的TCP SYN,为该TCP分配TCP缓存和变量(消耗资源哟),然后向客户TCP发送允许连接的报文段。
首先,server端也将自己的SYN比特被置为1,其次,该TCP的首部确认号字段(ack)被置为client_isn+1,也就是告诉对方“嗯我收到啦,你接着说吧”。最后,服务器选择自己的初始序号(server_isn),并将其放到TCP报文段首部的序号字段中一并发送给客户端。
这其实就是另一个商人告诉对方,我已经收到你的信息(client_isn),我可以和你做生意(ACK),你接着说吧(client_isn+1),我的信息是(server_isn)
第三次握手:在收到SYNACK报文段后,客户端也要给该连接分配缓存和变量。这时客户主机首先会通过将值server_isn+1放置到TCP报文段首部来对服务器允许连接的报文段进行确认(ack=server+1)。因为这时连接实际上已经建立了,所以同步位SYN被置为0。这时客户端和服务端都已经进入ESTABLISHED状态,故第三次握手时,可以携带客户到服务器的数据。
嗯,收到对方答复后,第一个商人就会认为信任渠道已经建立,开始给对方备货(分配缓存和变量),然后出于礼貌告诉对方,你的信息我收到了,当然快递里可以带着自己的货物一块发过去。

3. TCP四次挥手


嗯,我们知道交易市场有好有坏,有时候生意不好做,那么合作伙伴之间的合作也会告一段落,我们来接着聊TCP关闭时的四次挥手。
来,先上张图。





第一次挥手:首先客户端发送FIN=1,seq=u(相当于前面已经传过去的最后一个字节的序号+1)这时客户端进入FIN-WAIT1状态,等待服务端确认。
第二次挥手:服务端收到连接后立即发出确认,确认号是ack=u+1,而这个报文段自己的序号seq=v(相当于服务端前面已经传送过的最后一个字节的序号+1),随后服务端即进入CLOS-WAIT状态,即客户端已经没有数据需要发送。但服务端若发送数据,客户端还是要接收的。客户端收到来自服务端的确认后就进入了FIN-WAIT-2状态等待服务端发出的连接释放报文段。
第三次挥手:若此时服务端已经没有向客户端发送的数据,其应用进程就通知TCP释放连接。这时服务端使FIN=1,假定当前最后一次确认发送的序号为w(seq=w)。并且需要重复发送上次确认过的确认号ack=u+1。这时服务端就进入LAST-ACK状态,等待客户端确认。
第四次挥手:客户端收到服务端的连接释放信号后,在确认号中把ACK置为1,确认号是ack=w+1,而自己的序号仍然是seq=u+1,接着客户端进入TIME-WAIT状态。为了保证服务端收到报文,会等待一段时间,一般是30秒,之后进入CLOSED状态,并且释放客户端所有资源,而服务端收到ACK报文后同样进入CLOSED状态
注意上面的服务端和客户端是相对的~~~全双工嘛
现在我们来一块思考一个问题,为什么建立连接三次握手就可以,而断开连接却需要四次挥手呢
你想啊,在做生意,尤其是离得比较远的两个商人,一方说我这边没有货了,生意能说关就关么?不能啊,路上可能还有没到的货物啊,你们总得对对账啥的吧。
就是这个道理,服务端收到FIN请求后,很可能并不会立刻关闭socket,因为这时服务端可能还有数据需要发送,所以不能和建立连接是一样直接发送ACK和SYN(ACK用来应答,SYN用来同步)只能先回复一个ACK报文,说你的FIN报文我收到了。只有等到服务端所有报文都发送完了,这时才能发送FIN报文,从而关闭TCP连接。
所以呢,还是需要四次挥手。
1 0
原创粉丝点击