使用 POCO Frame 识别半开连接中套接字的状态

Identify state of socket in half-open connection using POCO Frame

我有一个问题,然后我正在尝试重新连接服务器,使用我的代理中的 Poco。在连接会话结束时,我从服务器收到 FIN、ACK 包。然后 TCP 发送 ACK 来应答服务器关于接收他们的 FIN。所以我有半开连接。我的套接字已关闭,无法读取但无法发送。等待几秒钟后,我发送了 http 请求,

auto& requestStream = mSession->sendRequest(request);
Poco::StreamCopier::copyStream(request.stream(), requestStream);

auto& responseStream = mSession->receiveResponse(response);
Poco::StreamCopier::copyStream(responseStream, response.send());

TCP 发送 FIN、ACK 并发送 SYN 以启动另一个连接会话,因此我在 SSL_Read() 上收到异常。

解决这个问题的一种方法是使用关闭来识别套接字状态

if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN)
    reconnect();

但它不合法,bcs SSL* sslSecureSocketImpl _impl 的私有字段,也是 ServerSocketImpl 的私有字段。

你遇到过这个问题吗?

这是screen of wireshark。

好的,这个问题要POCO关注才能解决。我建议我的方式。

在我的例子中,服务器没有发送 SSL_shutdown,所以我的套接字是打开的。

您应该事先检查套接字是否为空并抑制此异常。之后您可以检查,该服务器在重新连接之前已发送 SSL_shutdown() 。然后你应该使用重新连接来恢复你的会话。

Here 描述了如何破解以检查套接字的状态。

class HttpsClientSession : public HTTPSClientSession {

public:
    using Super::HTTPSClientSession;

    ostream& sendRequest(HTTPRequest& request) override {
            if (connected() && socket().poll(Poco::Timespan(0), Socket::SELECT_READ)) {
                    try {
                            peek();
                    } catch (const SSLConnectionUnexpectedlyClosedException&) {
                            reconnect();
                    }

                    auto sock = static_cast<SecureStreamSocketImpl*>(socket().impl());
                    auto ssl = PRIVATE_ACCESS(PRIVATE_ACCESS(*sock, _impl), _pSSL);

                    if (SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN)
                            reconnect();
            }

            return HTTPSClientSession::sendRequest(request);
    }
};

¯\_(ツ)_/¯