TCP详解

 

 

TCP协议是TCP/IP协议族中一个重要到的协议。和IP协议相比,TCP协议更靠近应用层,因此在应用程序中具有更强的课操作性。

一、TCP服务的特点

传输层协议主要有两个:TCP协议和UDP协议,相对于UDP协议而言,TCP协议是面向连接的字节流服务,具有可靠传输的特点。

使用过TCP协议通讯到的双方必须先建立连接,然后才能开始数据的读写,双方都必须为连接分配必要的内核资源,以用来管理连接状态和连接上数据的传输。TCP连接是全双工的,即双方的数据读写可以通过一个连接进行,完成数据交换之后,通讯的双方都必须断开连接以释放系统资源。

TCP协议的这种连接是一对一连接进行,所以基于广播和多播(目标是多个主机地址)的应用程序不能使用TCP服务,二五连接协议UDP则非常适合广播和多播。

TCP协议是字节流服务,这种服务体现在发送端应用程序连续执行多次写操作时,TCP模块先将这些数据放入TCP发送缓冲区中,当TCP模块真正开始发送数据时,发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文发出,因此,TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系。

当接收端收到一个或多个TCP报文段后,TCP模块将他们携带的应用程序数据按照TCP报文段的序号依次放入TCP的接收缓冲区中,并通知应用程序读取数据。接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读出,也可以分多次读取,这取决于用户指定的应用程序度缓冲区的大小,因此,应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间没有固定的数量关系。

                                                                               TCP字节流服务

                                                                              UDP数据报服务

TCP传输是可靠的。首先,TCP协议采用发送应答机制,即发送端发送的每个TCP报文段都必须的到接收方的答应,才认为 这个TCP报文段传输成功,其次,TCP协议采用超时重传机制,发送端在发送出一个TCP报文段之后启动定时器,如果在定时时间内未收到应答,它将重发该报文段。

二、TCP头部结构

TCP头部信息出现在每个TCP报文段中,用于指定通信的源端端口,目的端端口,管理TCP连接等。

1.TCP固定头部结构

TCP头部结构如下图所示,其中诸多字段为管理TCP连接和控制数据流提供了足够的信息。

                                                                                    TCP头部结构

16为端口号(port number):告知主机给报文段来自哪里(源端口)以及传给哪个上层协议或应用程序(目的端口)的。

32位序号(sequence number):一次TCP通讯(从TCP 连接建立到断开)过程中某一个方向上的字节流的每个字节的编号。假设主机A和主机B进行TCP通讯,A发送给B的第一个TCP报文段中,序号值被系统初始化为某个随机值ISN(Initial Sequence Number,初始序号值)。那么在该方向上(A到B),后续的TCP报文段中序号值将被系统设置成ISN加上该报文段所携带数据的字一个字节在整个字节流的偏移。

32位确认号(acknowledgement number):用作对另一方发送来的TCP报文的响应。其值是收到的TCP报文段的序号值加1,假设主机A和主机B进行TCP通信,那么A发送出的TCP报文段不仅携带自己的序号,而且包含对B发送来的TCP报文段的确认号。反之,B发送出的TCP报文段也同时携带自己的序号和对A发送来的报文段的确认号。

4位头部长度(header length):标识该TCP头部有多少个32bit字(4字节)。因为4位最大能表示15,所以TCP头部最长是60字节。

6位标志位包含如下几项:

·URG标志,表示紧急指针(urgent pointer)是否有效。

·ACK标志,表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。

·PSH标志,提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间(如果应用程序不将接收到的数据读走,他们将会一直停留在TCP接收缓冲区中)。

·RST标志,表示要求对方重新建立连接。我们称携带RST标志的TCP报文段为复位报文段。

·SYN标志,表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段。

·FIN标志,表示通知对方本端要关闭连接了,我们称携带FIN标志的TCP报文段为结束报文段。

16位窗口大小(window size):是TCP流量控制的一种手段,这里说的窗口,指的是接收通告的窗口(Receiver Windows,RWND)。他告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送字节的速度。

16位校验和(TCP checksum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输的过程中是否损坏。注意,这个校验不仅包括TCP头部,也包括数据部分。这也是TCP可靠传输的一个重要保障。

16位紧急指针(urgent pointer):是一个正的偏移量,它和序号字段的值相加表示最后一个紧急数据的下一字节序号。因此,确切地说,这个字段是紧急指针相对当前序号的偏移,可以称之为紧急偏移。TCP的紧急指针是发送端向接收端发送紧急数据的方法。

三、TCP三次握手

服务器通过listen系统调用,进入LISTEN状态,被动等待客户端连接,因此执行的是所谓被动打开。服务器一旦监听到某个连接的请求(收到同步报文段),就将该链接放入内核的等到队列中,并向客户端发送带SYN标志的确认报文段。此时链接处于SYN_RCVD状态。如果服务器成功地接收到客户端发送回的确认报文段,则该连接转移到ESTABLISHED状态。ESTABLISHED状态是连接双方能够进行双向数据传输的状态。

客户端通过调用concect系统调用主动与服务器建立连接。connect系统调用首先给服务器发送一个同步报文段,使连接转移到SYN_SENT状态。此后,connect系统调用可能因为如下两个原因失败返回:

(1).如果connect连接的目标端口不存在(未被任何进程监听),或者该端口仍处于TIME_WAIT状态的连接所占用,则服务器给客户端发送一个复位报文段,connect调用失败。

(2).如果目标端口存在,但connect在超时时间内未收到服务器的确认报文段,则connect调用失败。

connecct调用失败将使连接立即返回到CLOSED状态。如果客户端成功收到服务器发送来的同步和确认报文段,则connect调用返回成功,连接转移至ESTABLISHED状态。

期间客户端与服务器三次交互数据的过程就称为三次握手。

                                                               TCP三次握手状态转移图

四、TCP四次挥手

当客户端执行主动关闭时,它将会向服务器发送一个结束报文段,同时连接进入FIN_WAIT_1状态。若此时客户端收到服务器专门用于确认的确认报文段,则连接转移至FIN_WAIT_2状态。当客户端处于FIN_WAIT_2状态时,服务器处于CLOSE_WAIT状态,这一对状态是可能发生半关闭状态,如果此时服务器也关闭连接,则客户端将给予确认并进入TIME_WAIT状态。

处于FIN_WAIT_2状态的客户端要等待服务器发送结束报文,才能转移至TIME_WAIT状态,否则它将一直停留在这个状态。如果不是为了在半关闭状态下继续接收数据,连接长时间的停留在FIN_WAIT_2状态并无益处。

连接停留在FIN_WAIT_2状态可能发生在:客户端执行半关闭后,未等服务器关闭连接就强行退出了,此时客户端连接有内核来接管,可称之为孤儿连接(和孤儿进程类似)。Linux为了防止孤儿连接长时间存留在内核中,定义了两个内核变量:/proc/sys/net/ipv4/tcp_max_orphans和/proc/sys/net/ipv4/tcp_fin_timeout.前者指定内核能接管的孤儿连接的数目,后者指定孤儿连接在内存中生存的时间。

四次挥手即是主动断开方与被动断开方,断开连接时四次交互的过程。

                                                                     TCP四次挥手状态转移图

五、TIME_WAIT状态

客户端连接在收到服务器的结束报文段之后,并没有进入CLOSED状态,而是进入了TIME_WAIT状态,在这个状态,he护短连接要等待一段长为2MSL(Maximum Segment Life,报文段最大生存时间)的时间,才能完全关闭。

TIME_WAIT状态存在的原因有两点:

(1).可靠的终止TCP连接。

(2).保证让迟来的TCP报文段有足够的时间被识别并丢弃。

第一个原因很好理解。假设上图这中用于确认服务器结束报文段(3)的TCP报文段(4)丢失,那么服务器将重发结束报文段。因此客户端需要停留在某个状态以处理重复收到的结束报文段(即向服务器发送确认报文段)。否则,客户端将以复位报文段来回应服务器,服务器认为这是一个错误,因为他期望的是一个像TCP报文段(4)那样的确认报文段。

TIME_WAIT状态的第二个原因:在Linux系统上,一个TCP端口不能被同时打开多次(两次及以上)。当一个TCP连接处于TIME_WAIT状态时,我们将无法立即使用该连接占着的端口来建立一个新的连接。反过来思考,如果不存在TIME_WAIT状态,则应用程序能够立即建立一个和刚关闭的连接相似的连接(这里说的相似,是指他们具有相同的IP地址和端口号)。这个新的连接被称为原来连接的化身。新的化身可能接收到属于原来的连接的、携带应用程序数据的TCP报文段(迟到的报文段),这显然是不该发生的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值