您的位置:首页 > 理论基础 > 计算机网络

TCP建立连接(三次握手)和释放(四次挥手)的详细解释

2016-12-06 16:17 573 查看
TCP建立连接(三次握手)和释放(四次挥手)的状态图,接下去所有的文字将描述这个图:



在客户端和服务器端还没有建立连接,分别处于closed状态,当要开始建立连接的时候:

①到⑥是两个主机建立连接三次握手的过程。⑦到 ⑩是释放连接的过程。

① 服务器端会创建一个应用程序,一般情况下运行着welcome socket 程序。该应用进程对应的套接字的标示符为*.443,*.*(意味着本地地址为*.443,*为通配符,意思是该应用程序接收目的地址为任意 目的端口号为443的报文段。*.*意味着来源地址为任意的ip地址和任意的端口号,之所以都是任意因为服务器根本不知道来自某客户端的SYN报文段的ip和端口号,同时客户端分配的端口号也不是固定的
即用即收)。 

这个应用程序创建后处于listen状态,等待来自客户端的SYN报文段,并且这个应用进程只能接受连接建立请求报文即所谓的SYN,或者可以发送确认报文等。但是不能接受来自客户端的携带数据的报文段,那么这个携带数据的报文段给谁呢?请看下面分析。

 <hr/>

第一次握手

②客户端某个应用程序要给服务器发送数据,在客户端TCP协议随机的在49152~65535端口号之间选择一个未被使用的端口号,然后创建一个套接字通过该端口号来唯一的标识。与此同时会给服务器发送一个SYN报文段。这个SYN报文段携带着一些与服务器预先协商的重要的信息:目的IP地址,源IP地址,目的端口号,源端口号,初始化序号(虽然SYN中没有数据,但是规定要消耗一个序号,这个序号根据一定的规则随机的变化)SYN位设置为1,窗口信息,MSS(最大报文数据部分的长度)。如下所示:

 


 

客户端发送出去之后 即将报文段交给了网络层之后,该应用进程处于SYN sent状态,即所谓的设立计时器开始计时以便于超时重传,接收来自客户端的确认。

 

以上是在服务器端存在一目的端口的情况下即存在有一个应用监听者客户端发来的SYN请求。但是如果服务器关掉了 或者不存在这么一个进程的话怎么办?

这就要使用到复位报文段。对于UDP而言如果发送到对方运输层向上交付失败,那么将会产生一个ICMP端口不可达的信息。但是对于TCP来说是返回一个复位报文段信息。

在这个复位报文段信息中,同样也要消耗一个序号,并且RST位设置为1确认序号将进入ISN加上数据字节数。接收方收到RST报文段之后通知应用进程进行相应的处理。

 <hr/>

第二次握手

③服务器接收到来自客户端发来的SYN报文段之后,检查SYN报文段中的源IP和源端口号然后分用到①创建的*.443,*.*对应的套接字中,对应的应用程序得到通知后知道一个客户端要想跟这个服务器建立连接,所以这个应用程序(一般为welcome socket)调用相应的函数创建一个套接字,这个套接字通过SYN报文段中的目的IP地址,源IP地址,目的端口号,源端口号唯一标识,同时这个套接字处于established状态,意味着再次从客户端发来的携带数据的报文段将发往这个套接字,但是这个创建的套接字不能接收SYN报文段。

 

*.443,*.*套接字收到SYN后发送一个确认ACK同时也发送服务器相关的信息SYN,转化为等待接收确认的状态。同时在报文段中也有目的IP地址,源IP地址,目的端口号,源端口号,初始化序号(虽然SYN中没有数据,但是规定要消耗一个序号)SYN位设置为1,ACK位设置为1,窗口信息,MSS(最大报文数据部分的长度)信息,但是不同的是在发送SYN顺便携带了对上一个SYN报文段的确认,由于客户端发往服务端的序号为0所以这个确认号为1.变为SYN
RCVD
状态



<hr/>

 

④ 客户端发送SYN之后开始处于等待接收服务器发来的ACK的状态,但是由于发送的SYN报文段在网络中丢弃或者超时等情况,导致回到初始closed状态,重新随机分配一个初始序号重新发送SYN。

<hr/> 

第三次握手

⑤客户端接收到服务器发来的SYN报文段之后,一查看,在报文段中有对发送的SYN报文段的确认,所以会将发送窗口向后移动一个。同时要发送一个对服务器发送的SYN的确认。这个确认可以携带数据信息。从这个状态开始客户端就可以给服务区发送数据了。

 

为什么在三次握手的过程中要有最后一次确认呢?

 

一、避免服务器端因为得不到ACK对发送的SYN的确认一直等待状态,也防止对SYN的重传。

二、防止已经失效的SYN报文段又到达了服务器端,服务器又为这个报文段创建一个套接字,然后发送SYN+ACK,但是客户端对应的应用程序又创建了一个新的套接字,所以对于这个再一次发来的旧的套接字的确认客户端并不会理睬。又如果客户端新创建的SYN收到确认后也不会发送确认的话,那么服务端并不知道创建的哪一个套接字是正确的能和客户端通信的。

⑥服务端接收到对发送SYN的确认。



<hr/> 
以上是建立连接的过程。
在established过程中双发已经建立了一条逻辑链路,所以可以互相发送信息。
一下是释放链接的过程。
<hr/>
⑦ 客户端应用程序已经没有任何数据要发送了,开始建立连接释放请求,并停止发送数据,主动关闭TCP连接,虽然停止了发送数据,但是可能在发送缓存中还存在这一部分未收到确认的数据。发送的FIN报文段中FIN位设置为1,如果之前传递过数据的话那么ACK位设置为1,虽然FIN报文段没有数据部分,和SYN一样也要消耗一个序号。



客户端发送完FIN之后处于FIN wait1
的状态。存在这个等待的状态的原因:
一、当客户端接收到该FIN之后 可能在这之前还存在着多个报文段要处理,所以要把FIN报文段缓存一段时间,然后等到处理这个FIN报文段之后才会向客户端发送确认信息。
二、没有收到FIN的确认,所以要等待,以便于超时重传。
<hr/> 
⑧假设服务器收到FIN,并且在这之前的所有的在接收缓存中的数据都处理完了之后发送ACK(发送的ACK信息如下)。进入了close wait状态。在这个状态下 服务器端会向上层应用程序提交一个EOF,通知引用进程对方已经关闭了连接。同时在发送缓存中还存在着一些数据,所以要花费一段时间传递这些数据。



 
⑨客户端收到了对FIN确认之后,进入了FIN wait2的状态,进入这个状态的原因是:
这个状态正式和close wait状态相对应,即等待着对方提交EOF到应用进程,同时等待着对法发送缓存中剩下的数据。
  
在⑨之后到⑩之前整个连接处于半关闭状态,客户端不能像服务前发送数据,但是反之可以。
 <hr/>
⑩服务器端发送FIN,意味着发送缓存中已经没有任何数据要发送。发送完毕之后处于Last ACK状态等待着接受FIN的 确认。
 


思考 :能不能将服务器端中⑧和⑩即分别发送的确认和FIN合并到一起发送呢?
 <hr/>
⑪接受到服务器端的FIN之后,发送ACK确认。注意并不会携带数据,因为已经不能发送了。发送ACK之后进入了time wait状态。

 


处于time wait 状态,时间大约是2MSL。一个MSL意味着是任何报文段被丢弃前在网络中的最长的时间,也就是说是一个有限的时间,意味着2MSL经过之后,在网络环境中已经不存在任何的报文段,要么被接受发接受,要么就是丢弃。那么有这个状态的原因是:

一、放置最后一次发送ACK没有到达服务器,从而服务器中FIN将重传,在这个时间内可以再一次接收到重传的FIN再一次进入time wait 状态发送确认ACK等待对法确认。

二、可能在之前的所有的报文段传输过程中可能在网络中存在滞留的报文段,为了不影响后面的其他应用进程的操作,所以要等待滞留的报文段丢弃。

三、还要注意的是,如果客户端处于time wait 状态,终止这个程序然后马上开启一个同样的程序之后不会发生影响,因为这两个程序对应的端口号不同。但是对于服务器来说终止一个正在处于time wait 状态的程序,然后马上开启另一个一样的程序,由于服务器一般使用的端口是熟知端口,由于终止的旧的程序处在time wait 状态占用着某个数值端口,但是在创建的这个新的程序又要去申请这个端口显然申请失败。

 <hr/>

(12)服务器接收到对FIN确认之后从last ACK状态转变到初始的closed状态,意味着对应的套接字将删除端口号将收回。

(13)当2MSL过后客户端也传遍到初始的closed状态,对应的套接字也删除。连接完全释放。

<hr/> 
这是正常的释放连接,而有些情况下不会释放连接而是直接把服务器或者客户端断电处理,也就是意味着断电的一方将清除相应的套接字和应用程序,但是另一方还保持着连接状态当再一次充电连接的时候又回到closed状态双方新建套接字重新建立一条心的连接,所以这种非法的释放可能导致一方存在大量的半打开TCP连接状态的应用。所以要避免。
 
 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息