TCP协议
TCP协议,即传输控制协议
(英文全拼:Transmission Control Protocol)。 其是一种面向连接的、可靠的、基于字节流的传输层通信协议。 TCP通信
需要经过创建连接
、传送数据
、终止连接
三个步骤。在通信传输之前,先要打开一个连接,连接关闭后无法再发送数据。
TCP通信类似生活中的“打电话”,打电话之前,必须要先拨打对方的电话号码请求建立连接,接通后双方才能通信,而电话挂断后就不能再进行通信了。
TCP特点
1.面向连接
进行TCP通信的双方必须先建立连接,然后才能进行数据的传输,双方都必须为该连接分配必要的系统内核资源,以管理连接的状态和连接上的传输。 双方间的数据传输都在这一个连接上进行。完成数据交换后,双方必须断开此连接,以释放系统资源。并且这种连接是一对一的。
2.可靠传输
TCP通过4种机制实现可靠传输:
1)TCP采用发送应答机制
TCP发送的每个报文段都必须得到接收方的应答,如此才会认为这个TCP报文段传输成功。
2)超时重传
发送端发出一个报文段之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个报文段。
TCP为了保证不发生丢包,就给每个包一个序号,序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK)。如果发送端实体在合理的往返时延(RTT)内未收到确认,那么就会假设对应的数据包已丢失将会进行重传。
3)错误校验
TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和。
4)流量控制和阻塞管理
流量控制用来避免主机发送得过快而使接收方来不及完全收下。
3.基于字节流
TCP是一种流模式协议(steam protocol),数据是以字节流的形式进行传输的,其中传送的字节流中的每个字节都按顺序编号。
TCP发送字节流数据流程:
(1)先将某次发送的数据作为一个数据块暂存到发送缓存区,发送时在缓存区先后打包成TCP报文段和IP数据包后发送(由于缓存区不止存在此次发送的数据,一个数据块可能会被分割成一部分与其他数据块一同被打包成TCP报文段);
(2)TCP报文段包含TCP首部
和TCP数据
两部分,首部包含源端口号
和目的端口号
、字节序号及确认号等信息;该TCP报文段被进一步包装,成为IP报文段,包含IP首部
和IP数据部分
,IP首部包含源IP地址
和目的IP地址
等信息,IP数据部分即是TCP报文段;
(3)网络链路层会根据源IP地址、目的IP地址和源端口号、目的端口号确定连接的双方,把IP数据包发送到接收端的接收缓存区;
(4)接收端应用程序从接收缓存区读取数据块,根据字节序号将数据重组成完整数据,即成功接收到消息;
简要总结一下TCP即是:TCP协议是建立在IP协议之上的,负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。
建立TCP连接-3次握手
建立一个TCP连接时,需要客户端和服务端进行“3次握手”,以确认建立连接。“3次握手”是对客户端和服务端通过发3个包来确认建立连接的比喻。
3次握手
的流程如下图所示:
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认;
(2)第二次握手:Server收到数据包后由标志位“SYN=1”知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态;
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
为何非要3次握手?
一次、两次握手建立连接的不可行性:
1)一次握手建立连接,即客户端发送一个请求连接的数据包即建立连接:由于TCP协议的接收应答机制,一次握手肯定不行,一方面服务端可能没有接收到这个请求,另一方面客户端也无法知晓服务端是否接收到了这个请求;在这种情形下建立的连接非常不可靠,可能只是客户端单方面的分配连接资源,而服务端完全不知道情形;
2)两次握手建立连接,即客户端和服务端各发送一个数据包即建立连接:第一次握手是客户端请求建立连接,第二次握手是服务端响应连接请求,然后服务端即分配资源建立连接。但是服务端的响应连接请求的信号客户端可能没有接收到,由于TCP协议的接收应答机制,客户端会再次发出建立连接的请求,这样服务端又会再次分配资源建立连接,而前一次连接就会是占系统用资源的无效连接。假设服务端每次发送的数据一直在丢失,客户端一直SYN,服务器就会产生多个无效连接,占用资源,这个时候服务器可能会挂掉。这个现象就是我们听过的“SYN的洪水攻击”。
三次握手建立连接的可行性:
第一次握手是客户端发起建立连接的请求,然后服务端响应此请求表示可以建立连接进行了第二次握手,最后第三次握手是客户端对服务端表示可以建立连接的再次响应,代表客户端接收到了服务端发出的可以连接的信号。这之后双方都能确认对方接收到了自己的信号,因此可以开始分配资源建立连接传输数据。三次握手能够建立可靠的连接。
四次、五次握手的不必要性: 由于三次握手即可以创建可靠的连接了,四次、五次握手就没有必要了。
形象一点TCP三次握手就像我们打电话,第一方会先“喂,听得到我说话吗?”,另一方“嗯,听到了,你听得到我说话吗?”,第一方又说“也听得到”,双方都确认对方能听到自己说话后才开始真正的交流。断开TCP连接-4次挥手
断开客户端和服务器的TCP连接需要经过“四次挥手”。
第一次挥手:主机1(可以是客户端,也可以是服务器端),设置Sequence Number
和Acknowledgment Number
,向主机2发送一个FIN
报文段;此时,主机1进入FIN_WAIT_1
状态;这表示主机1没有数据要发送给主机2了;
第二次挥手:主机2收到了主机1发送的FIN
报文段,向主机1回一个ACK
报文段,Acknowledgment Number
为Sequence Number
加1;主机1进入FIN_WAIT_2
状态;
第三次挥手:主机2向主机1发送FIN
报文段,请求关闭连接,同时主机2进入CLOSE_WAIT
状态;这表示主机2告诉主机1,我也没有数据要发送了,可以进行关闭连接了;
第四次挥手:主机1收到主机2发送的FIN
报文段,向主机2发送ACK
报文段,然后主机1进入TIME_WAIT
状态;主机2收到主机1的ACK
报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
问题
1.为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
首先,MSL即Maximum Segment Lifetime,就是最大报文生存时间,是任何报文在网络上的存在的最长时间,超过这个时间报文将被丢弃。《TCP/IP详解》中是这样描述的:MSL是任何报文段被丢弃前在网络内的最长时间。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒、1分钟、2分钟等。
TCP的TIME_WAIT需要等待2MSL,当TCP的一端发起主动关闭,三次挥手完成后发送第四次挥手的ACK包后就进入这个状态,等待2MSL时间主要目的是:防止最后一个ACK包对方没有收到,那么对方在超时后将重发第三次挥手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可以继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。
2.client发送完最后一个ack之后,进入time_wait状态,但是他怎么知道server有没有收到这个ack呢?莫非sever也要等待一段时间,如果收到了这个ack就close,如果没有收到就再发一个fin给client?这么说server最后也有一个time_wait哦?求解答!
因为网络原因,主动关闭的一方发送的这个ACK包很可能延迟,从而触发被动连接一方重传FIN包。极端情况下,这一去一回,就是两倍的MSL时长。如果主动关闭的一方跳过TIME_WAIT直接进入CLOSED,或者在TIME_WAIT停留的时长不足两倍的MSL,那么当被动关闭的一方早先发出的延迟包到达后,就可能出现类似下面的问题:1.旧的TCP连接已经不存在了,系统此时只能返回RST包2.新的TCP连接被建立起来了,延迟包可能干扰新的连接,这就是为什么time_wait需要等待2MSL时长的原因。
3.为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。