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
?
答
有在你的代码中的一些错误:
SocketImpl si = null;
这个声明重叠类字段只setOption
作品在套接字打开/连接-
时,你必须关闭套接字完成
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(); } }
}
答
如果你看一下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。这就是你得到这个错误的原因。
java.net.SocketException套接字已关闭此异常意味着您关闭了套接字,然后继续尝试使用它,您是否可以提供socketImpl代码 –