Reputation: 739
I am trying to set the SO_KEEPALIVE
time of socket.
I created a class SocketBuilder
to build the socket instance with SocketImpl. Source code is below,
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();
}
}
}
I am getting java.net.SocketException: Socket Closed
exception. If I remove the line si.setOption(SocketImpl.SO_KEEPALIVE, new Integer(60));
it works fine. But I want to set the SocketImpl.SO_KEEPALIVE
. How can I set the SO_KEEPALIVE
of socket?
Upvotes: 0
Views: 282
Reputation: 3602
If you look at the source code of AbstractPlainSocketImpl#setOption
method,
public void setOption(int opt, Object val) throws SocketException {
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
// Rest of the code removed for brevity
}
You can see there is a isClosedOrPending
check before setting the options.
/*
* 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;
}
}
}
In your case, since you are just creating a socket, it will not have any fd associated with it. That is why you are getting this error.
Upvotes: 0
Reputation: 4714
There some errors in your code:
SocketImpl si = null;
this declaration overlap your class field
setOption
works only when a socket open/connected
You must close socket when you finish
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();
}
}
}
Upvotes: 1