2012-06-10 50 views
3

我有一个阻塞的SSL BIO对象,我想发送数据。问题是连接在远程端被关闭,直到我执行读操作(BIO_write不会返回错误),我无法找到它。但是,在我发送之前我无法阅读,因为我不想阻止。最后,负责发送数据的代码和负责读取的代码是分开的,意味着失败的读取不能触发另一次发送。我该如何解决?如何确定阻止SSL BIO连接是否已关闭?

回答

1

有两种“关闭”状态,被称为“半关闭”状态。他们主要关心套接字的一端还是另一端将要发送更多应用程序数据。当您的recv调用返回0时,它实际上是通知您没有更多数据要接收。但是,发送数据还是可以的,除非send呼叫信号发出其他类型的错误信号,例如EPIPEECONNRESET(我不确定这些窗口与winsock等效的是什么,但我知道它们在那里)。如果SSL_write没有返回错误,那是因为套接字的另一端仍然接受数据。

recv呼吁允许“没有更多数据”状态的无阻塞检查,这是可以做到这样的:

char c; 
int r = recv(sock, &c, 1, MSG_DONTWAIT|MSG_PEEK); 

如果r0,插座已receved的迹象表明有从另一端没有更多待处理数据。否则,该调用将返回1以获得一个字节的数据(由于MSG_PEEK,它仍在输入缓冲区中)或-1。如果errnoEAGAIN(这可能是因为MSG_DONTWAIT)没有错误。应该查询任何其他errno值,但可能表明套接字处于无效状态,需要关闭。

插座被关闭之前,OpenSSL的应用程序应该确保SSL_shutdown返回1。然后,插座上的closeSSL对象被破坏(与​​)后发生。这意味着,除非应用程序出现异常,否则使用OpenSSL的套接字的双方应该已经看到SSL_shutdown返回1,然后双方都可以安全地关闭连接。

如果您想检查您的SSL上下文的关闭状态,可以使用SSL_get_shutdown,它将报告另一端是否已启动SSL_shutdown序列。

相关问题