我有一个阻止的SSL BIO对象,我想将数据发送到。问题是连接在远程端关闭,直到我读取才能找到它(BIO_write不会返回错误)。但是,在我发送之前我无法阅读,因为我不想阻止。最后,负责发送数据的代码和负责读取的代码是分开的,这意味着失败的读取不能触发另一次发送。我该如何解决这个问题?
答案 0 :(得分:1)
有两种“关闭”状态,被称为“半关闭”状态。它们主要与套接字的一侧或另一侧是否将发送更多应用程序数据有关。当您的recv
调用返回0时,它实际上会通知您没有更多数据要接收。但是,发送数据仍然可以,除非send
调用发出其他类型的错误信号,例如EPIPE
或ECONNRESET
(我不确定这些错误的窗口等价物是什么winsock,但我知道他们在那里)。如果SSL_write
没有返回错误,那是因为套接字的另一端仍在接受数据。
recv
调用允许对“不再数据”状态进行非阻塞检查,并且可以这样做:
char c;
int r = recv(sock, &c, 1, MSG_DONTWAIT|MSG_PEEK);
如果r
为0
,则套接字已收到指示,表示另一端没有待处理的数据。否则,对于一个数据字节(由于1
而仍在输入缓冲区中)或MSG_PEEK
,调用将返回-1
。如果errno
为EAGAIN
(由于MSG_DONTWAIT
而可能),则不会出现错误。应查询任何其他errno
值,但可能表示套接字处于无效状态,需要关闭。
在套接字关闭之前,OpenSSL应用程序应该确保SSL_shutdown
已返回1.然后,套接字上的close
发生在SSL
对象被销毁之后(带有SSL_free
)。这意味着,除非应用程序执行异常操作,否则使用OpenSSL的套接字的两端应该看到SSL_shutdown
返回1
,然后双方都可以安全地关闭连接。
如果您想检查SSL
上下文的关闭状态,可以使用SSL_get_shutdown
,它会报告另一端是否已启动SSL_shutdown
序列。< / p>