TCP/IP协议详解

学过网络的同学可能都知道TCP有个三次握手和四次挥手,但是对于其中详细的解释却不太明白,那就让这篇文章来给你解惑吧······

TCP简介

  TCP是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。正如我们所知道的,一个TCP连接必须要经过三次“对话”才能建立起来。

三次握手

  首先简单的描述一下三次握手的过程:

    • 第一次:主机A向主机B发送同意连接和要求同步(就是说两台主机一个在发送,一个在接收)的数据包请求连接:“我想要给你发点数据”;
    • 第二次:主机B向主机A发送同意连接和要求同步的数据包:“可以,你什么时候发?”;
    • 第三次:主机A向主机B发送确认主机B的要求同步的数据包:“我现在就发。”

  到这为止,三次握手建立连接,并且主机A开始向主机B发送数据。

  然后再详细介绍一下三次握手:

    • 第一次:建立连接时,主机A发送SYN(一个含有同步序列号的标志位的数据段)包[SYN=1,seq=x]到服务器B,并进入SYN_SEND状态,等待主机B确认;
    • 第二次:主机B收到SYN包,必须确认主机A的SYN,同时自己也发送一个ACK(确认应答)包,即SYN+ACK包[SYN=1,ACK=1,seq=y,ack=x+1],此时主机B进入SYN_RECV状态;
    • 第三次:主机A收到主机B的SYN+ACK包,向主机B发送确认包ACK[SYN=0,ACK=1,seq=x+1,ack=y+1],此包发送完毕,主机A和主机B进入ESTABLISHED状态。

  三次握手完成后,客户端和服务器就建立了TCP连接。这时可以调用accept函数获得此连接三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换TCP 窗口大小信息。

  在socket编程中,客户端执行connect()时,将会触发三次握手。 下面用一张图来整体看一下过程:

      

四次挥手

  • 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求(首先A B端的TCP进程都处于established状态, 当A的应用程序传送完报文段,就会去主动关闭连接。A会停止发送报文段(但是还会接收),并向B发送[FIN = 1,seq=u]数据,之后进入FIN-WAIT-1状态);
  • 主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1(B接收到A发送的请求之后,会通知应用进程,A已经不再发送数据,同时B会向A发送ACK确认数据[ACK=1,seq=v,ack=u+1 ],B进入CLOSE-WAIT状态,A接收到B发送的数据之后,A进入FIN-WAIT-2状态;此时A到B方的连接已经关闭了(即半连接状态));
  • 由B 端再提出反方向的关闭请求,将FIN置1(当B的应用进程发现自己也没有数据需要传送,B应用进程就会发出被动关闭的请求,B此时向A发送[FIN=1,ACK=1,seq=w,ack=u+1]数据,并且进入LAST-ACK状态);
  • 主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束(A接收到B发送的数据之后,向B发送ACK确认数据[ACK =1,seq=u+1,ack=w+1],进入TIME-WAIT状态,等待2MSL之后正常关闭连接进入CLOSED状态;B接收到A发送的确认之后进入CLOSED状态。B到A方的连接关闭)。

  上图:

            

为什么建立连接协议是三次握手,而关闭连接却是四次握手呢? 

  这是因为服务端的LISTEN状态下的SOCKET当收到客户端的SYN报文的建立连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;

  但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。 

在已经成功建立连接的TCP连接,发生哪几种情况时会导致TCP产生严重错误,发送RST包?

  1. 端口未打开
  2. 请求超时
  3. 提前关闭
  4. 在一个已关闭的socket上收到数据

 

posted on 2018-01-09 10:42  python屌丝的逆袭  阅读(135)  评论(0编辑  收藏  举报

导航