使用wireshark抓包读懂tcp三次握手,四次挥手

tcp三次握手和四次挥手的描述不少,可是感受大部分文章看下来很难具象化这个过程,下面使用这个wireshark抓包工具,经过抓取到的数据包来理解一下,可以从另外一个角度理解tcp三次握手了html

完整案例代码已上传github: github.com/neatlife/my…java

wireshark下载地址:www.wireshark.org/download.ht…git

建立案例项目

能够在idea中建立一个maven项目,建立用来测试3次握手和4次挥手的两个模块,建立模块在idea右键菜单里就有: github

把握手和挥手分开测试是为了防止客户端在发送过程当中,服务端就提早关闭了,而后挥手的部分包可能会丢掉,这个丢包的效果能够自行尝试shell

编写握手客户端和服务端

服务端

创建一个socket服务器,并在8881端口上监听,核心代码以下:编程

ServerSocket socket = new ServerSocket(8881);
socket.accept();
TimeUnit.SECONDS.sleep(2);
socket.close();
复制代码

客户端

链接上面的服务器,并发送几回数据,每次发送几个字节的数据,核心代码以下:服务器

Socket socket = new Socket("127.0.0.1", 8881);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("111".getBytes());
outputStream.write("1111l".getBytes());
outputStream.write("11111l111l".getBytes());
socket.close();
复制代码

编写挥手客户端和服务端

服务端

核心代码以下:微信

ServerSocket serverSocket = new ServerSocket(8881);
Socket socket = serverSocket.accept();
socket.close();
serverSocket.close();
复制代码

客户端

核心代码以下:并发

Socket socket = new Socket("127.0.0.1", 8881);
socket.close();
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
复制代码

编写wireshark捕获过滤器

wireshark抓的包已经上传到github,能够直接使用wireshark打开案例项目里的握手包:handshake.pcapng,和挥手包:wave.pcapngsocket

捕获过滤器以下:

host 127.0.0.1 and port 8881
复制代码

填写到wireshark中:

启动抓包

抓取的握手的包

运行握手模块的服务端和客户端,查看wireshark抓到的包

右键新窗口能够查看大图

注意上面这个[TCP Window Update]包能够忽略,这个包是服务端用来控制客户端发送包的频率的,这个包不必定会有,具体能够参考TCP传输协议抓包经验

抓取挥手的包

分析抓到的包

预备知识: 要看懂上面wireshark抓的包,下面的这个指令须要提早了解下

标志位 做用
SYN 表示请求创建链接
FIN 表示请求断开链接
Seq 表示曾经发送过数据的字节数+1,0表示以前没有发送过数据
Len 本次收到的数据字节大小,0表示本次没有收到数据
ACK 表示对对方过来的请求的确认
Ack 表示期待下次对方发送过来的Seq指令的值

注意:

  1. 即便Seq不为0,并不表示曾经必定发送过数据,是否发送过数据须要依据Len指令的值有没有大于0的来判断。
  2. 3次握手和4次挥手过程当中通常是不会传送数据的,因此这个过程当中Len指令都是0

经微信读者“R.飞”指正,4次挥手过程当中是能够传数据的(未验证,有兴趣的读者能够自行验证)

经微信读者“ヤキモチ”指正,3次握手过程当中的第三次握手也能够传数据的(未验证,有兴趣的读者能够自行验证)

怎么确认握手有3次

握手过程当中没有只有指令交互,没有数据交互,因此开始的Len=0的全部交互都属于握手,效果以下

经过这个图,能够得出如下结论

  1. 客户端发送了两次请求到服务端,服务端发送了一次请求到客户端
  2. 第一次握手是客户端请求服务端,发送的syn指令表示客户端想要和服务端创建链接
  3. 第二次握手是服务端收到客户端发送的syn指令后,给客户端发送的ack指令,表示接受客户端想要创建链接的请求,同时服务端也给客户端发送了syn指令,表示服务端请求想要和客户端创建链接
  4. 第三次握手是客户端知道了服务端赞成链接了,而且也想发送数据给客户端,客户端回应一个ack,表示容许服务端给客户端发送数据

怎么确认挥手有4次

握手过程当中没有只有指令交互,没有数据交互,经过这个特性,从后往前数,找到全部Len=0的包便可,能够看到,只有4个这样的包

经过上面这个图,能够得出如下结论

  1. 客户端发送了两次请求到服务端,服务端发送了两次请求到客户端
  2. 挥手首先是客户端发起的
  3. 第一次挥手是客户端向服务端请求想要断开链接(FIN指令)
  4. 第二次挥手是服务端收到客户端的请求,并发送能够断开了的确认消息给客户端(ACK指令)
  5. 第三次挥手是服务端向客户端请求想要断开链接(FIN)
  6. 第四次挥手是客户端收到服务端的请求,并发送能够断开了的确认消息给服务端(ACK)

一些注意的点

即便这是个简单的分析也参考了一些资料

  1. TCP传输协议抓包经验
  2. <<NIO与Socket编程技术指南 (Java核心技术系列)>>
  3. <<TCP/IP详解·卷1:协议(原书第2版)>>

ACK和Ack做用是不一样的,ACK表示确认收到了数据,Ack表示下一次发过来的数据的序号

若是idea没法识别子模块中的java文件,可能须要从新import下模块的pom.xml

若是在操做过程当中遇到问题,可加做者微信探讨

wx
相关文章
相关标签/搜索