Java 8:如何为SSLSocket.startHandshake()执行超时

问题描述 投票:0回答:1

[我们有下面的线程执行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);
        }
    }
}
java multithreading sockets ssl handshake
1个回答
0
投票

您可以添加一个新字段:

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(..)'的情况下,它会起作用并抛出异常。

© www.soinside.com 2019 - 2024. All rights reserved.