为何同步方法SSLSocket.startHandshake()仍提供HandshakeCompletedListener回调?
Great question—this is one of those details that seems contradictory at first, but makes perfect sense once you dig into real-world use cases of SSL/TLS sockets in Java.
Let’s break down why the HandshakeCompletedListener matters even though startHandshake() is synchronous, and address your question about writing to the OutputStream:
1. Implicit handshakes happen automatically (without calling startHandshake())
You don’t always have to call startHandshake() explicitly. The JavaDoc states that if you attempt to write to the SSLSocket before any handshake has completed, the socket will automatically trigger a handshake. In this scenario, you never get the "signal" from a synchronous method return that the handshake finished. The listener becomes your only way to be notified when this implicit handshake completes—critical if you need to run post-handshake logic like validating peer certificates, logging session details, or initializing app-specific state tied to the secure connection.
2. Rehandshakes require non-polling notifications
SSL/TLS supports rehandshakes (renegotiating the secure session) after the initial handshake. These can be triggered explicitly by calling startHandshake() again, or even implicitly by the underlying protocol (e.g., if session keys need rotation). If you initiate a rehandshake in one thread but need another thread to know when it’s safe to resume operations, the listener provides a clean, efficient alternative to polling for handshake status. Polling would be clunky and waste system resources compared to a callback-based approach.
3. Robustness for edge cases
While startHandshake() is technically synchronous, there are rare edge cases where the handshake might complete at the protocol level, but the SSL implementation still needs to finish background processing (like session caching or post-handshake validation). The HandshakeCompletedListener guarantees you’re notified when the entire handshake process—including any implementation-specific post-steps—is truly done. This adds a layer of robustness that relying solely on startHandshake()’s return might miss.
Can you guarantee writing to OutputStream only after handshake completion?
- If you call startHandshake() explicitly: Yes, this is fully safe. The method blocks until the handshake is 100% complete, so any writes after it returns will be sent over an established secure session.
- If you rely on automatic handshakes: The first write operation will block until the handshake succeeds (or throws an exception if it fails). So your data won’t be sent until the handshake is done. However, you won’t get a proactive notification of the handshake finishing unless you use the listener—you’ll only know the write succeeded (or failed) when the call returns.
In short, HandshakeCompletedListener isn’t a replacement for the synchronous startHandshake() return. It fills gaps for scenarios where you don’t control when the handshake starts, need cross-thread notifications, or want to handle every possible handshake completion event (including implicit ones).
内容的提问来源于stack exchange,提问作者Arthur Attout

