好文分享
本文开始之前,分享一篇近期阅读过的好文,文章详情可点击AI杀疯!介绍一下有趣的AI算法。
此文介绍了几种有趣的AI算法及其应用,涵盖了视频生成、代码生成和游戏AI等领域,领略到了最新的AI技术的魅力与未来的无限潜力。
按照计划今天就要讲解和分享TCP协议的三次握手和四次挥手以及使用Wireshark抓取TCP/IP协议数据包的技能,能够深入分析TCP帧格式及“TCP三次握手”。通过抓包和分析数据包来理解TCP/IP协议,进一步加深对TCP包的理解和认识。
宏哥首先来一个我们日常工作中比较常见的例子:远程会议、视频或者打电话。先上图:
TCP的三次握手有点像我们远程有会议(疫情期间都遇到过吧);
1)A同事:喂!听得到我说话吗?(第一次握手A-->B);
2)B同事:听得到,你能听到我说话吗?(第二次握手B-->A);
3)A同事:听到了,我们可以开会了(第三次握手A-->B)。
一次完整的远程会议流程。
三次握手的过程,还是先上图:
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
宏哥首先来一个我们日常工作中比较常见的例子:和渣男/女分手、离婚。先上图:
故事简述:C和D是男女朋友,C有一天发现D是渣男,想跟D分手。
1)C向D提出分手请求(第一次挥手);
2)D收到请求后,虽然D是渣男,但是D还是很礼貌的,告诉C,我收到你的请求了;但是我现在忙着跟其他人谈恋爱昵(第二次挥手);
3)D终于空下来了,告诉C,我接受你的分手请求了(第三次挥手);
4)C收到D的回复后,告诉D我终于解脱(第四次挥手)。
四次挥手的过程,还是先上图:
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
今天宏哥还是以度娘为例,进行演示WireShark抓包实战,
1.首先我们来先看一下百度的IP是多少,想必都知道如何获取吧!方法很多,宏哥就要其中一种最简单的方法来看一下:通过ping命令即可: ping baidu.com ,如下图所示:
2.从上图可以看出其中39.156.66.10就是度娘的IP地址,后面需要通过这个IP地址,作为wireshark的过滤条件,方便我们找到对应的报文。
1.打开WireShark,并开启抓包模式开始捕获,如下图所示:
2.在命令行输入curl -I baidu.com
来向百度发送一个HTTP请求。如下图所示:
3.停止wireshark抓包。在wireshark的过滤器中,输入ip.addr == 39.156.66.10
来过滤发送给百度的请求。可以得到如下过滤后的报文。如下图所示:
4.从上图我们可以清楚地看到前三条是TCP三次握手建立连接的报文,中间三个是包括一个HTTP请求,一个TCP的确认报文和一个HTTP响应报文,响应报文的TCP确认报文和第一次挥手被放在了同一个报文里。后面的四条是TCP四次挥手断开连接的报文。
三次握手的第一个报文:SYN报文,也就是第一次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.根据之前理论知识,我们趁热打铁:首先,来看第一个报文,即三次握手的第一次握手。点击选中第一个TCP即可查看。如下图所示:
2.整个第一次握手的报文消息详细解析,都在上图中右边做了红色标注。我们来看比较重要的几个部分。
①开始是2字节的源端口号和2字节的目的端口号。
②紧接着的四个字节,表示的是客户端传送给服务端的初始序号,这是一个随机值,目的是维护安全。
③注意,再紧接着的四个字节是确认号, 不过,在第一次握手的报文中,ACK标志bit位是0,所以,实际上在第一次握手时,确认号是无意义的 ,因为这时候也没有什么需要确认的。
④再后面的4个bit,表示的是TCP头部长度,也可以理解为数据偏移量。 注意,这里是8,而该字段的单位是4字节,所以TCP头部是8*4 = 32字节 ;
⑤紧接着的是4个保留bit位,和8个特殊标志bit位。这些标志按顺序依次是CWR、ECE、URG、ACK、PSH、RST、SYN、FIN,关注ACK、SYN、FIN即可。这里SYN为1,表示是一个建立连接的报文,ACK为0,表示本报文的确认号无意义。
⑥后面2字节表示接收窗口大小,是用于流量控制的。
⑦再后面,是2字节的校验和,2字节的紧急数据指针。
⑧需要额外指出的是,此报文指出TCP头部有32个字节,而不是一般报文是20字节。这里是因为在选项部分,本报文携带了一些额外的数据,其中包括MSS(Maximum Segment Size): 1460 bytes 等信息。
三次握手的第二个报文:SYN+ACK报文,也就是第二次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.同样的方法:点击选中第二个TCP即可查看。如下图所示:
2.上图中右边红色部分标注了第二次握手的报文详细信息,其大部分都和第一次握手类似。来看比较重要的几个部分
①源端口号和目的端口号正好和第一次握手相反,说明这是服务端响应客户端的报文
②服务端给出了一个自己的初始序号A1 7C 07 91,对应2709260177。
③服务端的ACK bit位是1,说明该报文的确认号是有意义的,确认号对应的值是15 ec 6b df,恰好是第一次握手的报文的序号+1,表示在该数字之前的字节都已经收到,期望下一次收到的报文的序号是这个数
④这里TCP头部也有32字节,选项部分同样说明了自己的MSS等信息,这里的MSS给的值是1412字节。
总体上来说,第二次握手的报文和第一次握手的报文的区别在ACK bit位是1,并且确认号是第一次握手报文的序号+1,此外,两个报文都包括了额外的选项部分,并且头部都有32个字节。
三次握手的第三个报文:ACK报文,也就是第三次握手,如下图所示:
然后在WireShark中查看一下我们抓包抓到的是否正确,如下图所示:
1.同样的方法:点击选中第三个TCP即可查看。如下图所示:
2.上图中右边红色部分标注了第三次握手的报文详细信息,第三次握手的大部分内容也都是类似的,挑出重点部分。
①第三次握手的序号是第二次的确认号。确认号是第二次的序号+1。
②首部长度是20字节,头部没有了选项部分。
③SYN字段是0。这里是因为,第一次握手时客户端请求连接,第二次握手时服务器确认并接受连接,第三次握手实际连接已经成功建立。实际上,第三次握手是可以携带应用数据的,不过没见过这样做的。
④接收窗口的值一直在变化,这是流量控制的一部分,报文发送方发送自己的窗口大小,接收方根据对方窗口大小,调节报文发送速率。
到这里,TCP三次握手结束,连接成功建立。
从上面的过程可以发现 第三次握手是可以携带数据的,前两次握手是不可以携带数据的 ,这也是面试常问的题。
一旦完成三次握手,双方都处于 ESTABLISHED
状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。
客户端向服务端发送第三次握手的报文之后,连接建立成功后,紧接着会发送数据传输的信息。在这里是HTTP请求。来看这个请求对应的报文的信息。
1.同样的方法:点击选中HTTP请求即可查看。如下图所示:
2.首先,跟随宏哥来看HTTP层协议,将该部分翻译过来,就是图中的HTTP部分标注(左边红色部分)。包含了请求行、请求头、空行。 注意,这里的HTTP部分有73个字节,也是就说,TCP数据部分有73个字节 。
实际上,程序通过
IP层的数据总长度-IP头长度-TCP头长度
来计算数据长度。
3.然后再来看TCP协议部分(右边红色部分),主要有以下几点。
①该报文的头长度也是20字节
②该报文的确认号、序号都和第三次握手的一样。
③其中PSH bit为是1。这里是因为这个报文只有这一个分组,整个报文传输完毕,无需等待其他分组,通知接收方应当立即将报文交给应用程序,而不需要缓存起来等待足够的数据再交付给上层。
因为HTTP是基于TCP的协议,所以每一个HTTP请求,即使只有一个分组,也至少涉及到两个TCP报文的传输,因为接收方会发送一个确认报文给发送方。下面,来看这个http请求对应的TCP确认报文。
1.同样的方法:点击选中HTTP请求后TCP的确认报文即可查看。如下图所示:
这个报文内(右边红色部分),有以下几点需要注意。
①上一个HTTP请求的http部分有73个字节,所以本确认报文的确认号,就应当是上一个请求的序号+73。
②因为接收方直到目前没有传输数据给发送方,所以序号目前只是建立连接时确定的初始序号+1。
③这里PSH标志位的值没有置1,可以理解为只有携带了数据的报文的最后一个分组,才会将PSH标志位置为1。
也就是说,这个HTTP请求报文,涉及一次HTTP数据报文和一次TCP确认报文。如果数据量较大,需要分组传输的话,涉及的传输更多。
接下来的,就轮到HTTP响应的报文了,也就是服务端响应给客户端的HTTP报文。
1.同样的方法:点击选中HTTP响应即可查看。如下图所示:
2.这里和之前的没有太大区别(左边和右边红色部分),不过这一次,报文由服务端发送,并且携带了数据,这里携带了305字节的数据,所以,客户端接收后发送的确认报文的确认号,将会是本报文的序号+305。
3.接着看HTTP响应对应的TCP确认报文,实际上,这个也是第一次挥手的报文。
HTTP响应对应的TCP确认报文,实际上,这个也是第一次挥手的报文。第一次挥手和HTTP响应的确认报文是同一个报文,和其他的报文相比,除了FIN bit位被置为1,并没有什么其他区别。如下图所示:
1.同样的方法:点击选中第一次挥手的TCP即可查看。如下图所示:
HTTP响应对应的TCP确认报文(左边红色部分):
①因为响应携带了305字节的数据,所以本次确认报文的确认号是之前的确认号/接收到报文的序号+305。
②这里ACK为1,表示确认号有意义,FIN为1,表示这是一个断开连接的报文,所以,这也是第一次挥手的报文。
1.同样的方法:点击选中第二次挥手的TCP即可查看。如下图所示:
2.第二次挥手的报文,由服务端发出,对第一次挥手的报文进行了确认。并且其中FIN是0(从上图可以看到),因为该报文只是接收方对发送方的第一次挥手报文的确认。
服务端准备断开连接,准备好后,服务端发出FIN报文。也就是第三次挥手。
1.同样的方法:点击选中第三次挥手的TCP即可查看。如下图所示:
注意,这里FIN是1,这是由服务端发出的FIN报文,表示服务端准备好断开连接。服务器发送该报文后,进入LAST_ACK阶段。
当客户端接收到此报文(第三次挥手)时,会返回最后一条确认报文给服务端。也就是第四次挥手。
1.同样的方法:点击选中第四次挥手的TCP即可查看。如下图所示:
2.服务端接收到这条确认消息后,并不会再发送报文,而是将连接关闭,进入CLOSED状态。
前边理论加后边的实践,想必小伙伴或者童鞋们对TCP包有了进一步的认识了吧,宏哥觉得说清楚了,如果有想了解更清楚地,可以查一些资料。好了,今天时间也不早了,就到这里!感谢您耐心的阅读~~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。