2017-04-06 118 views
0

我試圖設置套接字的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

有在你的代碼中的一些錯誤:

  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

0

如果你看一下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。這就是你得到這個錯誤的原因。