--- title: TCP/IP categories: - TCP/IP tags: - TCP date: 2022-08-22 21:45:25 --- # TCP/IP协议详解 ## 一、什么是TCP/IP TCP/IP是现代Internet的核心技术,由IETF定义。互联网传输都需要依靠TCP/IP族,其包含HTTP、Telnet、FTP、RIP、UDP等等 ## 二、TCP/IP协议模型 ![1](https://lzcwy-1257903760.cos.ap-beijing.myqcloud.com/%E7%BD%91%E7%BB%9C/TCPIP/1.png) ## 三、TCP/IP工作流程 ![2](https://lzcwy-1257903760.cos.ap-beijing.myqcloud.com/%E7%BD%91%E7%BB%9C/TCPIP/2.jpg) **源主机封包:** 1、 **应用层:**源主机将数据向下传输给传输层; 2、 **传输层:**将数据分组,加上TCP首部形成TCP数据段,向下传输给网络层; 3、 **网络层:**给TCP数据段加上源主机、目的主机IP首部,生成IP数据包,向下传输给链路层; 4、 **链路层:**链路层在其MAC帧的数据部分装上IP数据包,再加上源主机,目的主机的MAC地址和帧头,并根据其目的的MAC地址,将MAC帧发往目的主机或IP路由器; **目的主机拆包:** 1、 **链路层:**在目的主机,链路层将MAC帧的帧头去掉,并将IP数据包向上传递给网络层; 2、 **网路层:**检查IP报头,如果报头中校验和计算结果不一致,则丢弃该IP数据包,若校验和计算结果一致,则去掉IP报头,将TCP数据段向上传递给传输层; 3、 **传输层:**检查顺序号,判断是否是正确的TCP分组,然后检查TCP报头数据,若正确,则向源主机发送确认信息,若不正确或丢包,则向源主机要求重发信息; 4、 **应用层:**目的主机,传输层去掉TCP报头,将排好顺序的分组组成应用数据流送给应用程序,这样目的主机接收到的来自源主机的字节流,就像是直接接收来自源主机的字节流一样。 ## 四、TCP报文格式 ![3](https://lzcwy-1257903760.cos.ap-beijing.myqcloud.com/%E7%BD%91%E7%BB%9C/TCPIP/3.gif) 上图中 TCP 报文中每个字段的含义如下: **源端口和目的端口字段** TCP源端口(Source Port):源计算机上的应用程序的端口号,占 16 位。 TCP目的端口(Destination Port):目标计算机的应用程序端口号,占 16 位。 **序列号字段** CP序列号(Sequence Number):占 32 位。它表示本报文段所发送数据的第一个字节的编号。在 TCP 连接中,所传送的字节流的每一个字节都会按顺序编号。当SYN标记不为1时,这是当前数据分段第一个字母的序列号;如果SYN的值是1时,这个字段的值就是初始序列值(ISN),用于对序列号进行同步。这时,第一个字节的序列号比这个字段的值大1,也就是ISN加1。 **确认号字段** TCP 确认号(Acknowledgment Number,ACK Number):占 32 位。它表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。其值是接收计算机即将接收到的下一个序列号,也就是下一个接收到的字节的序列号加1。 **数据偏移字段** TCP 首部长度(Header Length):数据偏移是指数据段中的“数据”部分起始处距离 TCP 数据段起始处的字节偏移量,占 4 位。其实这里的“数据偏移”也是在确定 TCP 数据段头部分的长度,告诉接收端的应用程序,数据从何处开始。 **保留字段** 保留(Reserved):占 4 位。为 TCP 将来的发展预留空间,目前必须全部为 0。 **标志位字段** - CWR(Congestion Window Reduce):拥塞窗口减少标志,用来表明它接收到了设置 ECE 标志的 TCP 包。并且,发送方收到消息之后,通过减小发送窗口的大小来降低发送速率。 - ECE(ECN Echo):用来在 TCP 三次握手时表明一个 TCP 端是具备 ECN 功能的。在数据传输过程中,它也用来表明接收到的 TCP 包的 IP 头部的 ECN 被设置为 11,即网络线路拥堵。 - URG(Urgent):表示本报文段中发送的数据是否包含紧急数据。URG=1 时表示有紧急数据。当 URG=1 时,后面的紧急指针字段才有效。 ACK:表示前面的确认号字段是否有效。ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1。 - PSH(Push):告诉对方收到该报文段后是否立即把数据推送给上层。如果值为 1,表示应当立即把数据提交给上层,而不是缓存起来。 - RST:表示是否重置连接。如果 RST=1,说明 TCP 连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。 - SYN:在建立连接时使用,用来同步序号。当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当 SYN=1,ACK=1 时,表示对方同意建立连接。SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中 SYN 才为 1。 - FIN:标记数据是否发送完毕。如果 FIN=1,表示数据已经发送完成,可以释放连接。 **窗口大小字段** 窗口大小(Window Size):占 16 位。它表示从 Ack Number 开始还可以接收多少字节的数据量,也表示当前接收端的接收窗口还有多少剩余空间。该字段可以用于 TCP 的流量控制。 **TCP 校验和字段** 校验位(TCP Checksum):占 16 位。它用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个数值,接收端根据接收的数据校验生成一个值。两个值必须相同,才能证明数据是有效的。如果两个值不同,则丢掉这个数据包。Checksum 是根据伪头 + TCP 头 + TCP 数据三部分进行计算的。 **紧急指针字段** 紧急指针(Urgent Pointer):仅当前面的 URG 控制位为 1 时才有意义。它指出本数据段中为紧急数据的字节数,占 16 位。当所有紧急数据处理完后,TCP 就会告诉应用程序恢复到正常操作。即使当前窗口大小为 0,也是可以发送紧急数据的,因为紧急数据无须缓存。 **可选项字段** 选项(Option):长度不定,但长度必须是 32bits 的整数倍。 ## 五、TCP三次握手 ![4](https://lzcwy-1257903760.cos.ap-beijing.myqcloud.com/%E7%BD%91%E7%BB%9C/TCPIP/4.png) 1. TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态; 2. TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。 3. TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。 4. TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。 5. 当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。 ## 六、TCP四次挥手 ![5](https://lzcwy-1257903760.cos.ap-beijing.myqcloud.com/%E7%BD%91%E7%BB%9C/TCPIP/5.png) 1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。 2. 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。 3. 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。 4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。 5. 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗ *∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。 6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。