Wireshark抓包分析TCP,发现居然只有三次挥手

背景

本人一直不喜欢背八股文,喜欢源码调式和测试,相信自己看到的,所以一直苦于怎样去学习网络协议。昨天看了一篇文章《简单的 HTTP 调用,为什么时延这么大?》,里面有用到Wireshark抓包工具分析了耗时原因。趋于好奇心,网上了解一下Wireshark怎样使用,发现一篇好文《(图文并茂,权威最详细)Wireshark抓包分析 TCP三次握手/四次挥手详解》,自己动手安装分析一波

搭建环境

  1. 下载Wireshark:https://www.wireshark.org/#download(版本为3.6.0)
  2. 安装Wireshark:针对于windows来说,比较傻瓜,一直下一步即可
  3. 打开Wireshark
    3.1 点击WLAN进入
    Wireshark抓包分析TCP,发现居然只有三次挥手_第1张图片
    3.2 配置过滤器(参考:https://blog.csdn.net/aflyeaglenku/article/details/50884296),点击向右箭头践行过滤
    (1)因为我需要分析握手和挥手协议,所以我主要配置是ip.dst和ip.src过滤条件
    Wireshark抓包分析TCP,发现居然只有三次挥手_第2张图片
  4. 写测试代码,发送http请求
        @Test
        public void testTcp() throws Exception {
            String response =  HttpUtils.doGet("http://xxx,xxx,xxx,xxx:8082/exp-api/coe/api",null);
            System.out.println(response);
            Thread.sleep(1000 * 60 * 5);
        }
    

分析抓包结果

TCP三次握手

  1. TCP建立连接时,会有三次握手过程,如下图所示,wireshark截获到了三次握手的三个数据包。第四个包才是http的,说明http的确是使用TCP建立连接的
    Wireshark抓包分析TCP,发现居然只有三次挥手_第3张图片
  2. 跟着八股文,对照Wireshark抓包的数据进行对比分析
    2.1 看上图No=3819的信息,53622 端口是客户端,刚开始Flags确实SYN(也就是SYN=1),然后seq=0(正好符合SYN=1,Seq = X)
    2.2 No=3820,服务端(端口为8082),Flags为[SYN,ACK],Seq=0,Ack=1(因为客户端发送SYN报文的Seq=0,确认序号正好为 0 + 1)
    2.3 No=3821,客户端(端口为53622),Flags为[ACK],Seq=1(因为客户端发送SYN报文的Seq=0,下个报文序列化+1),Ack=1(因为服务端发送Seq=0,回复的序号需要加1)
    Wireshark抓包分析TCP,发现居然只有三次挥手_第4张图片

数据传输

Wireshark抓包分析TCP,发现居然只有三次挥手_第5张图片

  1. Http请求选中后,能够看到对应的请求和响应(用箭头表示对应的请求和响应)
  2. 通过上面的截图可以看到,在TCP三次握手建立连接后,客户端发送http请求,服务端收到请求后首先返回确认信息(ACK) ,待服务端处理完成后,将数据返回给客户端,发送ACK=1和PSH=1告知客户端将要发送数据,最后将数据返回给客户端,客户端对收到的数据进行确认,完成一次数据交互的过程。
  3. 在stack找到相关问题:https://stackoverflow.com/questions/64094996/tcp-server-sends-ack-followed-by-psh-ack,将其中回答进行翻译(google翻译)
    3.1 操作系统只用一个ACK来确认接收(数据包中没有任何数据)
    3.2 如果应用程序稍后决定发送一些东西,它将用PSH,ACK来发送
    3.3 服务端发送的数据太大,第一个包没有PSH标志(只有ACK),最后一个包将有标志PSH、ACK通知消息的结束

TCP四次挥手

  1. 在抓包之前都会认为四次挥手是必须的,但抓包的时候发现只有三次挥手(为什么?)
    Wireshark抓包分析TCP,发现居然只有三次挥手_第6张图片
    Wireshark抓包分析TCP,发现居然只有三次挥手_第7张图片
  2. 很诧异,为啥只有挥手只有3个数据包,stack查了一下:https://stackoverflow.com/questions/15182106/what-is-the-reason-and-how-to-avoid-the-fin-ack-rst-and-rst-ack
    2.1 [ACK]是确认之前发送的数据包已经被接收
    2.2 [FIN]是主机想要终止连接时发送的;TCP协议要求两个端点都发送终止请求(即FIN)
    2.3 客户端想要关闭连接,响应[FIN,ACK]表示收到了发送的数据包,并希望关闭会话,然后服务端响应一个[FIN,ACK]表明收到了终止请求(ACK部分),并且也将关闭连接(FIN部分)
  3. 看seq和ack的值是没有问题的,感觉第二次和第三次貌似是合并在一起了,并没有分成两次来发送
    3.1 在《Linux的TCP实现之:四次挥手》有描述原因:因为开启了延时ack机制 ,导致收到第一个fin之后,发送ack的条件不能满足立即发送ack的条件,导致ack的发送被延时了,在延时的过程中,应用如果确认没数据要发,并且也要关闭此连接的情况下,会触发发送fin,这个fin就会和之前的ack合并被发出

束语

  1. 因为第一次用Wireshark抓包分析TCP,可能有些分析不是太正确,欢迎指正和讨论
  2. 在看八股文的时候,一定要去验证,你会发现很多有趣的事情。譬如我在抓包的时候发现挥手时,其实可以不用四次挥手了。在大多数情况下三次挥手也够了

你可能感兴趣的:(杂谈,wireshark,tcp/ip,网络协议)