TCP之报头格式——连接建立与拆除

来源:互联网 发布:如何从考勤机导出数据 编辑:程序博客网 时间:2024/04/28 09:53

在了解TCP的连接与拆除前,首先来看看什么是TCP:

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。

下图为TCP协议的报文段格式:


1. 源端口和目的端口

各占2字节,端口号加上IP地址,共同构成socket。互相通信的进程使用一对socket,包括协议、源IP、源端口、目的IP、目的端口,这五个元素唯一确定一个TCP连接。

2. 序号

占4字节,是TCP段所发送的数据部分第一个字节的序号。在TCP传送的数据流中,每一个字节都有一个序号。建立连接时,发送方将初始序号(Initial Sequence Number, ISN)填写到第一个发送的TCP段序号中。

3. 确认号

占4字节,是期望收到对方下次发送的数据的第一个字节的序号,也就是期望收到的下一个TCP段的首部中的序号,等于已经成功收到的TCP段的最后一个字节序号加1。确认号在ACK标志为1时有意义,除了主动发起连接的第一个TCP段不设置ACK标志外,其后发送的TCP段都会设置ACK标志。

4. 数据偏移

占4比特,表示数据开始的地方离TCP段的起始处有多远。实际上就是TCP段首部的长度。由于首部长度不固定,因此数据偏移字段是必要的。数据偏移以32位为长度单位,因此TCP首部的最大长度是60(15*4)个字节。

5. 控制位

一共6个,占6比特,设置为1时有效。按顺序依次为:URG、ACK、PSH、RST、SYN、FIN。

紧急 URG:此位置 1,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送。

确认 ACK:仅当 ACK = 1 时确认号字段才有效,TCP 规定,在连接建立后所有传达的报文段都必须把 ACK 置 1。

推送 PSH: 当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP 就可以使用推送(push)操作,这时,发送方 TCP 把 PSH 置 1 ,并立即创建一个报文段发送出去,接收方收到 PSH = 1 的报文段,就尽快地(即“推送”向前)交付给接收应用进程,而不再等到整个缓存都填满后再向上交付。

复位 RST:用于复位相应的 TCP 连接

同步 SYN:仅在三次握手建立 TCP 连接时有效。当 SYN = 1 而 ACK = 0 时,表明这是一个连接请求报文段,对方若同意建立连接,则应在相应的报文段中使用 SYN = 1 和 ACK = 1。因此,SYN 置 1 就表示这是一个连接请求或连接接受报文。

终止 FIN:用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放运输连接。

6. 窗口

   占2字节,表示报文段发送方期望接收的字节数,可接收的序号范围是从接收方的确认号开始到确认号加上窗口大小之间的数据。

7. 校验和

校验和包含了伪首部、TCP首部和数据,校验和是TCP强制要求的,由发送方计算,接收方验证。

8. 紧急指针

URG标志为1时,紧急指针有效,表示数据需要优先处理。紧急指针指出在TCP段中的紧急数据的最后一个字节的序号,使接收方可以知道紧急数据共有多长。

9. 选项

最常用的选项是最大段大小(Maximum Segment Size,MSS),向对方通知本机可以接收的最大TCP段长度。MSS选项只在建立连接的请求中发送。


TCP的的连接建立:

TCP的建立通过3次握手来建立连接。连接可以由任意一方发起,也可以由双方同时发起。

下图是三次握手示意图:


第一次握手:建立连接时,客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。


为什么要第三次握手呢?
这主要是为了防止已失效的的连接请求报文段。 
假设,客户端发出连接请求报文段,但是该连接请求报文段在某个网络节点中长时间滞留,导致客户端因为超时又发送第二个链接请求报文段 。第二个连接请求与服务器建立连接,而第一个连接请求报文段以至于延误到连接释放以后才到达服务器。本来这个连接早已经失效了,如果只采用两次握手的话,服务器会误认为客户端又发送了一次连接请求,从而统一建立连接。所以,采用三次握手可以很好的避免这个问题。


TCP连接的释放:

下图是四次挥手示意图:


  • 由于TCP连接是全双工的, 因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  • TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。

  • 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。

  • 服务器关闭客户端的连接,发送一个FIN给客户端。

  • 客户段发回ACK报文确认,并将确认序号设置为收到序号加1。



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

  • 这是因为服务端的 LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发 送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文 多数情况下都是分开发送的。



1 0