一、TCP协议简介
因特网的运输层在应用程序断点之间传送应用程序报文,在这一层主要有两种传输协议 TCP和 UDP,利用这两种协议能够传输报文。
TCP 协议的全称是 Transmission Control Protocol 的缩写,意思是传输控制协议,HTTP底层采用TCP 作为通信协议,这是因为 TCP 是一种可靠的协议,保证通讯的数据不丢失。
TCP协议提供面向连接的服务,它能够控制并确认报文能够准确送达,并提供了拥塞机制来控制网络传输,因此当网络拥塞时,会抑制其传输速率。
TCP,提供面向连接的服务,在传送数据之前必须先建立连接,数据传送完成后要释放连接。因此TCP是一种十分可靠的的信息运输服务,为了实现可靠性,不可避免的增加了许多的开销,比如消息确认,网络流量控制等。
面对应用层的协议主要有 SMTP,TELNET,HTTP,FTP 等。
二、TCP的概述
TCP把连接作为最基本的对象,每建立一条TCP连接都连接两个端点,这种端点叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。
三、TCP特性
(TCP)传输控制协议,面向连接。是一种提供可靠数据传输的通用协议。
TCP提供一种全双工通信、面向连接的、可靠的字节流服务
在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP
TCP使用校验和,确认和重传机制来保证可靠传输
TCP给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
TCP使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
四、TCP报文组成
源端口和目的端口:各占2个字节,分别写入源端口和目的端口;
序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:(1)URG:紧急指针(urgent pointer)有效。
(2)ACK:确认序号有效。
(3)PSH:接收方应该尽快将这个报文交给应用层。
(4)RST:重置连接。
(5)SYN:发起一个新连接。
(6)FIN:释放一个连接。
窗口:占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
检验和:占2字节,校验首部和数据这两部分;
紧急指针:占2字节,指出本报文段中的紧急数据的字节数;
选项:长度可变,定义一些其他的可选的参数。
五、TCP建立连接(三次握手)
在进行三次握手(Three-way Handshake)建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。三次握手的目的是(1)、连接服务器指定端口;(2)、建立 TCP 连接,并同步连接双方的序列号和确认号;(3)交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手。
建立连接过程为:
1、最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器(客户端与服务端都要事先创建TCB传输控制块)。
2、客户端向服务器发送连接请求报文,报文中首部的同步位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。
TCP规定:SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
(大白话翻译:客户端A向服务端B喊到,我要向你发数据)
3、服务器收到客户端的请求连接报文后,同意连接时,就发出确认报文。报文中ACK=1,SYN=1,确认号为ack=x+1,同时服务端也要初始化一个序号seq=y,服务器进程进入了SYN-RCVD(同步收到)状态。
TCP规定:这个确认报文也不能携带数据,也要消耗一个序号。
(大白话翻译:服务端B听到后回答客户端A,好的没有问题,什么时候发过来?)
4、客户端收到确认报文后,还需要向服务端发送确认报文ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态
TCP规定:ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
(大白话翻译:客户端A收到B服务端的回答后,A可以确认的是A说的话B能听到,B的回到A也能听到,但是这个时候B还不知道B回答的话A有没有听到,这时就需要A再次应答一下)
关于为什么要进行第三次确认?
假设客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
六、TCP释放连接(四次挥手)
TCP释放连接的过程:
1、客户端和服务器都是处于ESTABLISHED状态,当客户端主动关闭,服务器被动关闭(客户端与服务端任何一方都可以主动释放连接)。
2、客户端发送释放连接的报文,同时停止客户端到服务端的数据传输,释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),客户端进入FIN-WAIT-1状态(终止等待1)。
TCP规定:FIN报文段即使不携带数据,也要消耗一个序号。
(大白话翻译:客户端A向服务端B说我不再传输数据给你了,A>B方向的连接关掉吧)
3、服务端收到客户端释放连接的报文后,发起确认报文ACK=1,ack=u+1,并且带上自己的序列号seq=v,服务端就进入CLOSE-WAIT状态(关闭等待)。服务器通知上层的应用进程,客户端向服务器的方向连接关闭,此时TCP连接处于半关闭状态。虽然此时客户端已经没有数据要发送了,但是服务器如果要发送数据给客户端,客户端还是要接受。这个状态可能要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
(大白话翻译:服务端B说好的,现在关闭A>B方向的连接,但是我还有数据要传给你,B<A方向的连接还不能关,等我发送完)
4、客户端收到服务端的确认报文后,客户端进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文。
(大白话翻译:客户端A收到回答后,默默地等待服务端要求关闭连接的报文)
5、服务器将需要发送给客户端的数据发送完毕后,向客户端发送释放连接的报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
(大白话翻译:服务端B对客户端A说我要发的数据都发完了,关闭连接吧!)
6、客户端收到服务端的关闭连接请求后,发送确认报文,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。
注意:注意这个时候TCP连接还是没有释放的,必须经过2MSL(最长报文段寿命)的时间后,才进入CLOSED状态。
(大白话翻译:客户端说好的,现在开始如果2MSL时间内没有收到任何报文,就关闭)
7、服务器收到客户端的确认报文后就立即进入CLOSED状态。
关闭连接需要等待2MSL的原因:
(1)、确认客户端发送的最后一个ACK报文到达了服务器,因为这个ACK报文可能丢失,服务端在已经发送了FIN+ACK报文请求断开了,客户端还没有给服务端回应,服务端会认为发送的请求断开报文客户端没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
(2)、防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。