我正在尝试设置套接字的SO_KEEPALIVE
时间。
我创建了一个类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 :(得分:1)
您的代码中存在一些错误:
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();
}
}
}
答案 1 :(得分: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。这就是你得到这个错误的原因。