2013-08-16 24 views
0

我有一个使用多个阻塞套接字的服务器线程,当需要处理数据时我需要它运行。问题是,我如何让OpenSSL做到“它的东西”(如重新协商)而不会陷入阻塞操作(等待应用程序数据)?注意:我有SSL_set_mode - SSL_MODE_AUTO_RETRY,我怀疑我不需要这样做,并且自己处理这些案例,但是从阅读文档中我不清楚我该如何实现这一点。请看下面的伪代码:使用select和多个阻塞套接字的OpenSSL重新协商

while(running){ 
    select on readability sockets 1 and 2 
    if(socket 1 readable) { 
     SSL_read data(socket 1) 
     process data, possibly interacting with socket 2 
    } 
    if(socket 2 readable) { 
     SSL_read data(socket 2) 
     process data, possibly interacting with socket 1 
    } 
} 

如果选择滴出,因为有SSL/TLS层“要做的事情”或者插座上,但没有应用层数据,会发生什么? SSL_read将处理“要做的事情”,但之后会因为没有应用程序数据而阻塞......该块会阻止从另一个套接字读取数据的能力。有很好的方法SSL_pending可以告诉我关于应用程序的数据,但是据我所知,堆栈没有机会获得任何没有SSL_read的数据。除了将套接字分成单独的线程或使用非阻塞套接字之外,是否有一种简单方法可以向OpenSSL层说几句话,如“如果需要,请重新协商,并在有数据记录的情况下读取数据记录,但不要阻止如果不需要“?像NULL/NULL读取或写入?

// process records on the socket 
SSL_read(ssl, 0, 0); // or maybe SSL_write(ssl, 0, 0) ? 
if (SSL_pending(ssl)) { 
    // do the application data read 
    SSL_read(ssl, buf, sizeof(buf)); 
} 

编辑:尝试了做SSL_read(ssl, 0, 0)没有选择读和阻塞的记录,以便将无法工作。做选择然后读取0/0或SSL_write(ssl, 0, 0)没有选择似乎不被阻止,虽然我还不确定是否正在做我所需要的事情...

+0

SSL_Pending用于预读,而不是用于您正在使用的目的。当完成下一次读取时,阻塞读取将自动重新协商。如果您使用的是ssl_set_fd,则可以在描述符上设置接收超时值,在这种情况下它可能会有所帮助。 http://stackoverflow.com/questions/4181784/how-to-set-socket-timeout-in-c-when-making-multiple-connections。否则可以使用非阻塞io。 –

回答

0

SSL_Pending是为了预读而不是为你正在使用的目的。当完成下一次读取时,阻塞读取将自动重新协商。如果您使用的是ssl_set_fd,则可以在描述符上设置接收超时值,在这种情况下它可能会有所帮助。 How to set socket timeout in C when making multiple connections?

否则可以使用非阻塞io。

+0

谢谢......我在两个套接字上都使用了'SSL_set_fd',并且我正在使用一个超时的'select'。我的问题是,当select指示套接字需要读取时,如何知道数据是否是重新协商(非应用程序数据)?如果它不是应用程序数据,那么'SSL_read'会很好地重新协商,但是它会阻止应用程序数据,这是问题所在。 – mark

+0

您需要在fd上设置SO_RCVTIMEO和SO_SNDTIMEO,当SSL_read完成协商后,它将在上述调用中设置的超时后返回,因此您不必担心始终等待读取部分。请不要我不想超时选择,但在fd。 –

+0

啊,我想你是建议继续让它阻止,只是使用接近零的东西... – mark