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轮再研究。

  • 相关阅读:
    (三)xpath爬取4K高清美女壁纸
    聚焦爬虫:数据解析
    (二)requests-爬取国家药监局生产许可证数据
    (一)requests-实战小练习
    requests模块
    spring+apache dbcp +oracle 连接池配置以及优化
    IntelliJ IDEA 注释模版 输入/**后 不显示配置好的模板
    oracle 隔离级别、事务怎么开始的以及如何查看数据库采用字符集
    java 日期处理相关
    Oracle 插入数据时获取系统时间
  • 原文地址:https://www.cnblogs.com/gordonkong/p/7298161.html
Copyright © 2011-2022 走看看