Java 8 : How to perform timeout for SSLSocket. 开始握手()

标签 java multithreading sockets java-8 handshake

我们有下面的线程来执行 SSLHandshake 但在某些边缘情况下我注意到 ((SSLSocket) clientSocket).startHandshake(); 被永远阻止并且它不会进入下一个 block while 循环代码,其中 SSL_HANDSHAKE_TIMEOUT 为 1500 毫秒并且工作正常,我想知道添加 clientSocket.setSoTimeout(90000); 是否会解决此问题或是否应该以不同的方式处理?

主服务器握手线程

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);
        }
    }
}

最佳答案

总结评论(主要来自@user207421):是的,通过 socket.setSoTimeout(timeout) 设置套接字超时如果握手过程在“一段时间”后仍未完成(但不一定 指定的超时时间1)。

这很简单,因为 setSoTimeout() 在套接字级别工作,在 SSL 握手之下:由 startHandshake() 执行的握手协议(protocol)涉及来自套接字Input/OutputStream 的多次读/写,这将触发超时本身。换句话说:它本身不是“握手超时”,而是握手本身执行的所有读取操作的“读取超时”。

另外请注意,您不需要自己调用 startHandshake():当您第一次尝试从 SSLSocket 读取或写入时,JVM 会自动执行此操作(无论如何,在从 SSLServerSocket 获得这样的套接字之后,您通常会尽早执行此操作)。


1:setSoTimeout(timeout) 指定的超时是针对单个 read() .因此,握手过程可能会在它执行的 read() 次数乘以您指定的 timeout 值后超时(在最坏的情况下)。

关于Java 8 : How to perform timeout for SSLSocket. 开始握手(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58307103/

相关文章:

当生成的文件位于另一个文件系统上时,Java 无法移动(重命名)文件

java - 在哪里下载 GlassFish 维护包?

c# - "Cross thread operation not valid"..在串行端口上读取数据时

Java - 此方法是多线程的吗?

java - 在 jython udp 数据包中发送原始十六进制数据

c - 如何在 linux 套接字编程中从服务器向客户端发送和接收字符指针数组 char *argv[]

java - Android 在启动应用程序时出现运行时错误

java - 在内存中执行 jar/class 文件

python - 如何正确关闭 tweepy 流

sockets - 从单个客户端到同一端口上同一服务器的最大连接数