[我们有下面的线程执行SSLHandshake,但在某些情况下,我注意到((SSLSocket) clientSocket).startHandshake();
被永久阻止,并且它不会进入while
循环代码的下一个块,其中SSL_HANDSHAKE_TIMEOUT为1500
毫秒,并且可以正常工作,Am想知道添加clientSocket.setSoTimeout(90000);
是否可以解决此问题,还是应该以其他方式处理?
MainServerHandshakeThread
public class MainServerHandshakeThread implements com.ssltunnel.utilities.threading.Shutdown, Runnable {
private final Socket clientSocket;
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MainServerHandshakeThread.class.getName());
private boolean done;
public MainServerHandshakeThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
private void handshake() throws CertificateExpiredException, InterruptedException, IOException {
long start = System.currentTimeMillis();
((SSLSocket) clientSocket).setNeedClientAuth(true);
MainServerHandshakeHandler handshake = new MainServerHandshakeHandler();
((SSLSocket) clientSocket).addHandshakeCompletedListener(handshake);
((SSLSocket) clientSocket).startHandshake();
while (!handshake.isDone() && !done) {
Thread.sleep(10);
long duration = System.currentTimeMillis() - start;
if (duration>SSL_HANDSHAKE_TIMEOUT) {
done = true;
LOG.warn("Handshake timeout");
}
}
long stop = System.currentTimeMillis();
serialNumber = handshake.getSerialNumber();
LOG.info("MainServer Handshake Handshake done in ms: " + ((stop - start))+" For serialNumber "+serialNumber );
}
@Override
public void run() {
try {
handshake();
} catch (CertificateExpiredException ex) {
LOG.error("Client Certificate Expired", ex.getMessage());
SocketUtils.closeQuietly(clientSocket);
}
catch (InterruptedException ex) {
LOG.error("Interrupted waiting for handshake", ex);
SocketUtils.closeQuietly(clientSocket);
}
catch (IOException ex) {
LOG.error("IO Error waiting for handshake", ex);
SocketUtils.closeQuietly(clientSocket);
}
finally {
LOG.debug("Handshake thread is done");
done = true;
}
}
@Override
public void shutdown() {
if (clientSocket!=null) {
SocketUtils.closeQuietly(clientSocket);
}
}
}
您可以添加一个新字段:
AtomicBoolean handShakeInitialised;
和新方法:
private boolean isHandShakeInitialised(SSLSocket socket) {
handShakeInitialised = new AtomicBoolean(false);
new Thread(() -> {
try {
socket.startHandshake();
} catch (IOException e) {
e.printStackTrace();
}
handShakeInitialised.set(true);
}).start();
return handShakeInitialised.get();
}
将startHandShake行替换为:
handShakeInialised = isHandShakeInitialised(((SSLSocket) clientSocket));
然后修改您的while条件:
while (!handShakeInitialised && !handshake.isDone() && !done) {..}
按照我的想法
clientSocket.setSoTimeout(90000);
[根据JavaDoc的帮助,在'read(..)'花费的时间过长而不是'startHandshake(..)'的情况下,它会起作用并抛出异常。