前段时间也是一直在找工作面试,而tcp的连接也是相对而言被问到比较多的一个问题,而我也是从一开始回答的支支吾吾,后续经过不断的查找资料,当后期再次被问到这个问题时,心里顿时美滋滋,这题我会哈哈。
那么想要了解连接,我们就得知道tcp头里面到底有哪些东西
首先我的来看一下在tcp建立连接的过程中常见的几个字段:
- SYN: 同步序号,SYN=1代表着 我想和你建立连接
- ACK: 确认序号,ACK = 0,代表着还未正式建立连接,ACK = 1,TCP规定,在连接建立后所有报文的传输都必须把ACK置1,那么我们就可以把ACK = 1,理解为确定建立连接
- seq: 一个随机生成的序号,占4个字节,范围是[0,2^32-1],超出之后重新从0开始,之所以是随机生成,也是为了防止第三方模拟客户端ip与服务器进行连接等
- ack: 确认字符,看上去和上文的ACK像,一个大写一个小写,其实它们代表的含义是完全不一样的,大写的ACK只有0和1,代表未确定连接和确定连接,而小写的ack是代表着回复字符,形象点的描述可以理解为,当A写了一封信给你B,描述了一个事情(seq),那么B在回信里面就得回复这个事情(ack),这就是ack的作用,通常我们回复都是ack = seq + 1,至于为什么需要加一,下文会进行解释
相信看了上面的描述,大家会对3次握手中存在的字段有了一个大致的印象,那接下来我们就仔细的讲讲在3次握手的过程中,这些字段都充当了什么角色
-
第一步 首先客户端是主动开启方, 发送SYN = 1,ACK = 0,seq = x(随机数)给服务端,在这一步可以理解为 客户端想和服务器建立连接,所以就向服务器发了信息(携带了一个密码x),确保了客户端发送数据功能的正常
-
第二步,服务器是被动开启方,收到客户端的数据后返回SYN = 1,ACK = 1,seq = y, ack = x + 1,这一步可以理解为 服务器收到客户端信息之后回复 我也想和你建立连接并且也携带了一个密码y,以及客户端的密码x+1,这里有一个问题,为什么x需要+1呢,其实呢是因为tcp为了方便区分头部可选字段(syn以及fin等)是否开启(也就是是否为1),所以规定所有携带syn以及fin等为1的,下一次应答号(ack)就必须+1,否则就不需要。也就是说+1仅仅是为了方便区分,并没有其他含义。而这次回信也确保了服务器接受能力以及发送能力的正常
-
第三步,客户端收到服务器的信息之后,回应ACK = 1,seq = x + 1, ack = y + 1, 这一步双方之前都已经打过招呼了,所以说就不需要再携带SYN啦,只需要回应一下客户端我收到了你的信息,你的密码为y+1,可是有个问题,为什么这次的seq为什么不是随机生成的呢?而是x+1呢,这里其实也是tcp的标准规定: ACK报文段可以携带数据,但如果不携带数据则不消耗序列号,但是在这种情况下,下一个数据报文段的序号仍然是 seq = x + 1。 而上一次客户端发送信息的时候是没有携带数据的,我们所有的seq,ack等都是头部字段,不属于携带数据,所以这一次的seq为x+1. 那么这一次回应的作用是什么呢? 这主要是为了防止已失效的连接请求报文段突然又传送到了服务器,因而产生错误。
ok,大功告成,其实tcp的连接是不是也没有想象的那么复杂,只要我们捋清楚了每个字段的作用整体的思路也就明确啦。妈妈再也不用怕我被问到3次握手了。
如有错误,欢迎大家指教。