面试题传送

TCP 报文格式

此处介绍建立或者断开TCP连接时,需要了解的TCP报文段首部字段含义:

序列号 seq:占4个字节(32位),用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号 seq 就是这个报文段中的第一个字节的数据序号。

确认号 ack:占4个字节(32位),期待收到对方下一个报文段的第一个字节的数据序号;序列号表示报文段携带数据的第一个字节的序号;而确认号指的是期望接收到下一个字节的序号;因此当前报文段最后一个字节的序号 +1 即为确认号。

TAG Description
URG 紧急指针标志,为 1 时表示紧急指针有效,为 0 则忽略紧急指针
ACK 确认序号标志,为 1 时表示确认号有效,为 0 表示报文中不含确认信息,忽略确认号字段
PSH PUSH 标志,PUSH 标志为 1 的 TCP报文段,接收方在接收到该 TCP报文段 以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队
RST 重置连接标志,用于重置由于主机崩溃或其他原因(拒绝非法的报文段或连接请求)而出现错误的连接
SYN 同步序号标志,用于建立 TCP 连接,在连接请求中,SYN=1,ACK=0;而连接响应中,SYN=1,ACK=1
FIN 断开连接标志,用于断开 TCP 连接,在断开连接请求中,FIN=1,ACK=0;而断开连接响应分两个步骤(需要传完全部数据),第一部分:FIN=0,ACK=1,第二部分:FIN=1,ACK=1

TCP 三次握手



第一次握手:建立连接时,客户端发送同步 SYN 包(seq=x)到服务器,并进入 SYN_SENT 状态,等待服务器确认;

第二次握手:服务器收到同步 SYN 包,必须返回给客户端一个确认 ACK(ack=x+1),同时自己也发送一个同步 SYN(seq=y),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;

第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认 ACK 包(ack=y+1),此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP连接成功) 状态,完成三次握手 。

TCP 三次挥手



第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为 seq=u(等于前面已经传送过来的数据的最后一个字节的序号加 1),此时,客户端进入 FIN-WAIT-1 状态。 TCP规定,FIN 报文段即使不携带数据,也要消耗一个序号;

第二次挥手:服务器收到连接释放报文,发出确认报文 ACK=1,ack=u+1,并且带上自己的序列号 seq=v,此时,服务端就进入了 CLOSE-WAIT(关闭等待)状态。服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个 CLOSE-WAIT 状态持续的时间;

第三次挥手:客户端收到服务器的确认请求后,此时,客户端就进入 FIN-WAIT-2 状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据);

第四次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文 FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w,此时,服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认;

四次挥手后的等待(确保服务端收到第四次挥手TCP报文):客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是 seq=u+1,此时,客户端就进入了 TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过 2MSL(最长报文段寿命)的时间后,客户端才会撤销相应的 TCB(Thread Control Block)线程控制块,进入 CLOSED 状态。而服务器只要收到了客户端发出的确认,立即撤销 TCB,进入 CLOSED 状态,结束这次 TCP 连接 。可以看到,服务器结束 TCP 连接的时间要比客户端早一些 。

常见面试题

【问题1】为什么建立连接的时候是三次握手,端口连接的时候却是四次握手?

(因为断开连接时,需要传完当前连接剩余的数据,而建立连接时,并不需要此步骤)

答:因为当 Server端 收到 Client端 的SYN连接请求报文后,可以直接发送 SYN+ACK报文。其中 ACK报文 是用来应答的,SYN报文 是用来同步的。但是关闭连接时,当Server端收到 FIN报文 时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK报文,告诉 Client 端,“你发的FIN报文我收到了”。只有等到我 Server 所有的报文都发送完了,我才能发送 FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

(为了确保 Server 收到了 ACK 报文段)

答:虽然按道理,四个报文都发送完毕,我们可以直接进入 CLOSE 状态了,但是我们必须假想网络是不可靠的,有可以最后一个 ACK报文 丢失。所以 TIME_WAIT 状态就是用来重发可能丢失的 ACK报文。在 Client 发送出最后的 ACK报文时,该ACK报文丢失。Server如果没有收到 ACK报文,将不断重复发送 FIN报文段。所以 Client 不能立即关闭,它必须确认 Server 接收到了最后的 ACK报文。Client会在发送出 ACK报文之后进入到 TIME_WAIT 状态。Client 会设置一个计时器,等待 2MSL 的时间。如果在该时间内再次收到 FIN报文,那么 Client 会重发 ACK报文 并再次等待 2MSL 的时间;所谓的 2MSL 是两倍的 MSL(Maximum Segment Lifetime),MSL 指一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间。如果等待了 2MSL 之后,Client 没有再次收到 FIN,那么 Client 推断 ACK报文 已经被 Server 成功接收,则结束 TCP 连接。

【问题3】为什么不能用两次握手进行连接?

(假设两次握手,可能发生两种异常情况)

答:三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,考虑计算机 Server 和 Client 之间的通信,假定 Client 给 Server 发送一个连接请求(SYN=1)分组,Server 收到了这个分组,并发送了确认应答(SYN=1,ACK=1)分组。按照两次握手的协定,Server 认为连接已经成功地建立了,可以开始发送数据分组 。但此时可能会有两种异常情况:

①.Client 的请求分组(SYN=1)在传输中被堵塞(并非丢失)的情况下,由于请求分组在网络中滞留的时间过长,Client 很久得不到 Server 的应答分组,将会发起第二个请求分组(SYN=1),Server 收到了第二个请求分组,即刻返回确认分组(SYN=1,ACK=1),建立连接;但第一个请求分组(SYN=1)并没有丢失(对于 Client 而言此请求分组已经丢失或者失效),在连接释放以后的某个时间才到达 Server,此时 Server 会误认为是 Client 又发出的新的建立连接请求,于是又返回确认分组(SYN=1,ACK=1),又建立了连接,但是 Client 实际上并没有发出请求分组(SYN=1),不会理睬 Server 的确认分组(SYN=1,ACK=1),也不会向 Server 发送数据,而 Server 却以为新的连接已经建立,并一直等待 Client 发送数据,这样就白白浪费了 Server 的许多资源 。

②.Server 的应答分组(SYN=1,ACK=1)在传输中被丢失的情况下,Client 将不知道 Server 是否已准备好,不知道 Server 建立什么样的序列号,Client 甚至怀疑 Server 是否收到自己的连接请求分组。在这种情况下,Client 认为连接还未建立成功,将忽略 Server 发来的任何数据分组,只等待连接确认应答分组 。而 Server 在发出的分组超时后,重复发送同样的分组 。这样就形成了死锁 。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

(保活计时器)

TCP连接设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接 。

TCP 连接的更多相关文章

  1. TCP连接的建立和终止

    TCP的简要要说明 标签(空格分隔): TCP 网络编程 Linux 面试 在此输入正文 一.TCP是什么 TCP全称传输控制协议(Transmission Control Protocol).TCP ...

  2. 简述TCP连接的建立与释放(三次握手、四次挥手)

    在介绍TCP连接的建立与释放之前,先回顾一下相关知识. TCP是面向连接的运输层协议,它提供可靠交付的.全双工的.面向字节流的点对点服务.HTTP协议便是基于TCP协议实现的.(虽然作为应用层协议,H ...

  3. HTTP的RST包与WinHttp延迟关闭TCP连接

    一.RST包也常见于断开TCP连接  几个月前用wireshark抓HTTP包发现有的网络通信在结束的时候没有使用四次握手,而是直接使用RST包.如: 在TCP协议中RST表示复位,用来异常的关闭连接 ...

  4. 一个完整的TCP连接

    当我们向服务器发送HTTP请求,获取数据.修改信息时,都需要建立TCP连接,包括三次握手,四次分手. 什么是TCP连接? 为实现数据的可靠传输,TCP要在应用进程间建立传输连接.它是在两个传输用户之间 ...

  5. 查看 Apache并发请求数及其TCP连接状态

    查看 Apache并发请求数及其TCP连接状态 (2011-06-27 15:08:36) 服务器上的一些统计数据: 1)统计80端口连接数 netstat -nat|grep -i "80 ...

  6. tcp连接listen的backlog剖析

    TCP连接中,最重要的是连接TCP连接上,两个方向之间的各个状态及各个系统调用与状态之间的关系.往往可以以两种图表示,第一种是状态转换图,第二种是连接时序图.如下: 状态图: 时序图:         ...

  7. 计算机网络(11)-----TCP连接的建立和释放

    TCP连接的建立和释放 概述 TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程,运输连接有三个阶段:连接建立,数据传送和连接释放. TCP连接的建立 如图所示,假定A主机是客户端程序, ...

  8. 查看 并发请求数及其TCP连接状态【转】

    服务器上的一些统计数据: 1)统计80端口连接数netstat -nat|grep -i "80"|wc -l 2)统计httpd协议连接数ps -ef|grep httpd|wc ...

  9. TCP连接的三次握手和四次解散过程

    客户端和服务器在使用TCP连接传输数据的过程中,需要经过三次握手建立连接和四次握手断开连接操作. 具体如下图所示 上图描述了TCP连接从建立到断开的详细过程,以下就其中的具体报文细节展开讨论. 在TC ...

  10. 传输层(2)-TCP连接的建立和终止、TIME_WAIT状态

    1.TCP连接的建立和终止 1)三路握手 客户端发送一个SYN(同步)分解,告诉服务器客户将在连接中发送的数据的初始序列号. 服务器发送确认客户的SYN(ACK),同时自己也得发送一个SYN分节,它含 ...

随机推荐

  1. Ribbon负载均衡服务调用

    1.在听周阳老师讲解时,使用Ribbon核心组件IRule时是这样用的: ribbon版本 : 自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,项目结构如下 MySelfR ...

  2. Atlas 2.1.0 实践(3)—— Atlas集成HIve

    Atlas集成Hive 在安装好Atlas以后,如果想要使用起来,还要让Atlas与其他组件建立联系. 其中最常用的就是Hive. 通过Atlas的架构,只要配置好Hive Hook ,那么每次Hiv ...

  3. Python虚拟环境配置应用

    Python好用,但用好却不易,其中比较头疼的就是包管理和Python不同版本的问题,为了解决这些问题,有不少发行版的Python,比如WinPython.Anaconda等,这些发行版将python ...

  4. 【链表】leetcode-1290-二进制链表转整数

    leetcode-1290-二进制链表转整数 题目描述 给你一个单链表的引用结点 head.链表中每个结点的值不是 0 就是 1.已知此链表是一个整数数字的二进制表示形式. 请你返回该链表所表示数字的 ...

  5. DDD的实体、值对象、聚合根的基类和接口:设计与实现

    1 前置阅读 在阅读本文章之前,你可以先阅读: 什么是DDD 2 实现值对象 值对象有两个主要特征:它们没有任何标识.它们是不可变的. 我们举个例子:小明是"浙江宁波"人,小红也是 ...

  6. 解决Spirng注入时名称下的红色波浪线

    解决Spirng注入时名称下的红色波浪线 报错情形: 解决办法: 方案一: 如果可以正常运行,那么可能是类没有交给Spring管理,如下图,我们只需要在对应的接口(或者类上)加上@Component注 ...

  7. Linux下运行java报错:Error: Could not find or load main class SocketIOPropertites

    [root@node01 testfileio]# javac SocketIOPropertites.java && java Soc ketIOPropertitesError: ...

  8. 宝塔Linux命令

    安装宝塔 Centos安装脚本 5.7:yum install -y wget && wget -O install.sh http://download.bt.cn/install/ ...

  9. 从源码解析Nginx对 Native aio支持_运维_youbingchen的博客-CSDN博客 https://blog.csdn.net/youbingchen/article/details/51767587

    从源码解析Nginx对 Native aio支持_运维_youbingchen的博客-CSDN博客 https://blog.csdn.net/youbingchen/article/details/ ...

  10. loj10018数的划分

    题目描述 将整数 n 分成 k 份,且每份不能为空,问有多少种不同的分法.当 n=7,k=3 时,下面三种分法被认为是相同的:1 1 5;1 5 1 ;5 1 1 输入格式 一行两个数 n ,k . ...