SocketImpl设置选项中的套接字关闭异常

问题描述:

我试图设置套接字的SO_KEEPALIVE时间。SocketImpl设置选项中的套接字关闭异常

我创建了一个类SocketBuilder来构建带有SocketImpl的套接字实例。源代码如下,

public class SocketBuilder { 

    private static SocketImpl si; 

    public static Socket createCVPSocket() throws Exception { 
     if (si == null) { 
      init(); 
     } 
     return new CSocket(si); 
    }  


    private static void init() throws SocketException { 
     @SuppressWarnings("rawtypes") 
     Constructor cons = null; 
     try { 
      cons = Class.forName("java.net.SocksSocketImpl") 
        .getDeclaredConstructor(); 
     } catch (NoSuchMethodException | SecurityException 
       | ClassNotFoundException e) { 
      throw new RuntimeException(
        "Not able to access socket implementation."); 
     } 
     cons.setAccessible(true); 
     SocketImpl si = null; 
     try { 
      si = (SocketImpl) cons.newInstance(); 
     } catch (InstantiationException | IllegalAccessException 
       | IllegalArgumentException | InvocationTargetException e) { 
      throw new RuntimeException("Not able to create instance of socket."); 
     } 
     if (si != null) { 
      si.setOption(SocketImpl.SO_KEEPALIVE, new Integer(60)); 
     } 
    } 

    private static class CSocket extends Socket { 
     protected CSocket(SocketImpl si) throws SocketException, Exception { 
      super(si); 
     } 
    } 
    public static void main(String[] args) { 
     try { 
      Socket sock = SocketBuilder.createCVPSocket(); 
      System.out.println(sock); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

我得到java.net.SocketException: Socket Closed异常。如果我删除行si.setOption(SocketImpl.SO_KEEPALIVE, new Integer(60));它工作正常。但我想设置SocketImpl.SO_KEEPALIVE。我怎样才能设置插座的SO_KEEPALIVE

+0

java.net.SocketException套接字已关闭此异常意味着您关闭了套接字,然后继续尝试使用它,您是否可以提供socketImpl代码 –

有在你的代码中的一些错误:

  1. SocketImpl si = null;这个声明重叠类字段只

  2. setOption作品在套接字打开/连接

  3. 时,你必须关闭套接字完成

    import java.lang.reflect.Constructor; 
    import java.lang.reflect.InvocationTargetException; 
    import java.net.*; 
    
    public class SocketBuilder { 
    private static SocketImpl si; 
    
    public static Socket createCVPSocket() throws Exception { 
        if (si == null) { 
         init(); 
        } 
        return new CSocket(si); 
    }  
    
    
    private static void init() throws SocketException { 
        @SuppressWarnings("rawtypes") 
        Constructor cons = null; 
        try { 
         cons = Class.forName("java.net.SocksSocketImpl") 
           .getDeclaredConstructor(); 
        } catch (NoSuchMethodException | SecurityException 
          | ClassNotFoundException e) { 
         throw new RuntimeException(
           "Not able to access socket implementation."); 
        } 
        cons.setAccessible(true); 
        si = null; 
        try { 
         si = (SocketImpl) cons.newInstance(); 
        } catch (InstantiationException | IllegalAccessException 
          | IllegalArgumentException | InvocationTargetException e) { 
         throw new RuntimeException("Not able to create instance of socket."); 
        } 
    
    } 
    
    private static class CSocket extends Socket { 
        protected CSocket(SocketImpl si) throws SocketException, Exception { 
         super(si); 
         super.bind(new InetSocketAddress("127.0.0.1", 8888)); 
    
         si.setOption(SocketImpl.SO_KEEPALIVE, Boolean.TRUE); 
        } 
    } 
    public static void main(String[] args) { 
        try { 
         Socket sock = SocketBuilder.createCVPSocket(); 
         System.out.println(sock); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
    } 
    

    }

+0

Jiaano,感谢您的快速响应。我会修复你提到的错误。我试过你分享的代码,但仍然收到相同的错误。 – Kajal

+0

你的错误是什么? –

+0

java.net.SocketException:套接字已关闭。我正在尝试更新代码,以确保在设置套接字选项之前连接处于活动状态。 – Kajal

如果你看一下AbstractPlainSocketImpl#setOption方法的源代码,

public void setOption(int opt, Object val) throws SocketException { 
     if (isClosedOrPending()) { 
      throw new SocketException("Socket Closed"); 
     } 
// Rest of the code removed for brevity 
} 

你可以看到有设置选项前的isClosedOrPending检查。

/* 
* Return true if already closed or close is pending 
*/ 
public boolean isClosedOrPending() { 
    /* 
    * Lock on fdLock to ensure that we wait if a 
    * close is in progress. 
    */ 
    synchronized (fdLock) { 
     if (closePending || (fd == null)) { 
      return true; 
     } else { 
      return false; 
     } 
    } 
} 

在你的情况,因为你只是创建一个插座,它不会有任何相关的FD。这就是你得到这个错误的原因。