• new Socket(host, port)阻塞解决


    如果服务器没有开启host,port。而客户端
    new Socket(host, port),则会产生阻塞。
    这样的话,我们甚至都没法关闭这个socket
    找了半天百度没有合理的解释,甚至有人说,强行stop Thread,我也是醉了。

    正确代码如下:

    //Socket client = new Socket(host, ip); //卡柱啦!不好啦怎办?
    
    //正确搞法
    //1. 直接new一个空的出来,这样不会卡柱。
    Socket client = new Socket();
    //2. 按照new Socket(host, port)的二次构造函数,调用
    InetSocketAddress address = host != null ? new InetSocketAddress(host, port) :
             new InetSocketAddress(InetAddress.getByName(null), port);
    SocketAddress localAddr = null;
    try {
         if (localAddr != null) //可以移除
             client.bind(localAddr);
         //3. 关键的,我们可以这里设置timeout。
         //即使不做timeout,我们可以在想关闭的时候,调用client.close也可以解决啦。
         client.connect(address, 500);
     } catch (IOException | IllegalArgumentException | SecurityException e) {
         try {
             client.close();
         } catch (IOException ce) {
             e.addSuppressed(ce);
         }
         throw e;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    阅读一下socket的源码,大致理解了。
    Socket类只是通过包装模式,创建和调用SocketImpl的方法。
    查看new Socket(host, port)就可以看到在构造函数就进行了createImpl() -> impl.connect(xx, timeout)导致了阻塞,所以无法返回Socket给你。因此这种情况,你确实没有很好的办法去停止socket。只能把线程弄死了。

    而类似的,我们按照上述我改造后的来使用,new Socket(),我们就得到了Socket对象。
    在connect之前内部也确保得到了impl。

    因此首先抄下我刚刚的代码,然后,想要解决阻塞问题,就有了2个合理的方案:

    1. client.connect(addr, timeout)的时候,我们可以设置第二个参数timeout,来保证连接的时候自动超时;
    2. client.connect(addr), 不做超时处理;我们也可以使用socket.close()来关闭。
  • 相关阅读:
    Fortify-设置中文语言
    计算机网络【HTTP请求构造与HTTPS】
    【计算机视觉】二、图像形成:1、向量和矩阵的基本运算:线性变换与齐次坐标
    Vue自定义指令
    Git add回退 & commit回退
    Ruby on Rails已死?GitLab:我还在用呢!
    机器学习从入门到放弃:硬train一发手写数字识别
    【MyAndroid】viewpage+cardView卡片海报效果展示--100个经典UI设计模板(99/100)
    JavaWeb-JSP技术简介
    哈尔滨商业大学计算机考研资料汇总
  • 原文地址:https://blog.csdn.net/jzlhll123/article/details/126169193