zoukankan      html  css  js  c++  java
  • Java网络编程学习A轮_03_抓包分析TCP四次挥手

    参考资料:
    http://www.jellythink.com/archives/705

    示例代码:
    https://github.com/gordonklg/study,socket module

    A. TCP 四次挥手

    下图描述了 TCP 整个生命周期从建立连接到断开连接的逻辑:



    下面的测试代码完美模拟了上图
    gordon.study.socket.basic.wireshark.TcpLifecycle.java

     1 public class TcpLifecycle {
     2 
     3     @SuppressWarnings("resource")
     4     public static void main(String[] args) throws Exception {
     5         new Thread(new Runnable() {
     6             @Override
     7             public void run() {
     8                 try {
     9                     ServerSocket serverSocket = new ServerSocket(8888);
    10                     Socket socket = serverSocket.accept();
    11                     socket.getInputStream().read();
    12                     socket.close();
    13                 } catch (Exception e) {
    14                 }
    15             }
    16         }).start();
    17 
    18         Socket socket = new Socket();
    19         socket.connect(new InetSocketAddress(8888));
    20         Thread.sleep(3000);
    21         socket.getOutputStream().write('a');
    22         socket.close();
    23     }
    24 }

    WireShark 的截图如下,解释都是多余的。

    B. Socket timeout

    Java 中的 socket 超时只针对读操作。

    gordon.study.socket.basic.wireshark.ClientSocketTimeout.java

     1 public class ClientSocketTimeout {
     2 
     3     @SuppressWarnings("resource")
     4     public static void main(String[] args) throws Exception {
     5         new Thread(new Runnable() {
     6             @Override
     7             public void run() {
     8                 try {
     9                     ServerSocket serverSocket = new ServerSocket(8888);
    10                     serverSocket.accept();
    11                     while (true) {
    12                         Thread.sleep(1000);
    13                     }
    14                 } catch (Exception e) {
    15                 }
    16             }
    17         }).start();
    18 
    19         try (Socket socket = new Socket()) {
    20             socket.connect(new InetSocketAddress(8888));
    21             socket.setSoTimeout(1000);
    22             socket.getInputStream().read();
    23         }
    24     }
    25 }

    由于第21行代码设置了 socket timeout,第22行代码中 read 方法最多阻塞1秒钟,如果无法从流中读取数据,则抛出 java.net.SocketTimeoutException。
    抛出异常后,主线程退出,由于使用了 try-with-resource,退出前会关闭客户端 socket,但是服务端永远在睡大觉,不会关闭 socket,所以整个 TCP 连接并没有完全关闭。

    从下边的 WireShark 截图可知,TCP四次挥手只走了一半(No.4 & No.5),服务端没有调用 close 方法,所以服务端处于 CLOSE_WAIT 状态,而客户端处于 FIN_WAIT_2 状态,下面的 CMD 截图可以证明。

    而 120 秒后(WireShark截图 No.228),FIN_WAIT_2 状态的 55421 端口主动向 8888 端口发送 RST 重置请求,最终两个异常状态都消失了。这应该是操作系统层面做的。这部分没有搞明白,放到B轮再研究。

  • 相关阅读:
    在TreeView控件节点中显示图片
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1146 Topological Order (25 分)
    PAT 甲级 1145 Hashing
    PAT 甲级 1145 Hashing
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1144 The Missing Number (20 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1151 LCA in a Binary Tree (30 分)
    PAT 甲级 1149 Dangerous Goods Packaging
  • 原文地址:https://www.cnblogs.com/gordonkong/p/7298161.html
Copyright © 2011-2022 走看看