M.V*_*.V. 1 c sockets ssl select timeout
我正在编写一个应用程序,该应用程序创建多个到 https 服务器的非阻塞 SSL 连接,在每个连接中我发送一个请求并读取服务器的响应。我的问题是,无论我做什么,我都无法确定响应数据何时完成。这是我负责发送和接收数据的代码的一部分:
....
fd_set connectionfds;
struct timeval timeout2;
FD_ZERO(&connectionfds);
FD_SET(socket_server, &connectionfds);
timeout2.tv_usec = 0;
timeout2.tv_sec = 1;
while(1)
{
r=BIO_read(io,buf,BUFSIZZ-1);
if (r>0){
//gather data
continue;
}
else if (SSL_get_error(ssl, r)==SSL_ERROR_WANT_READ){
int ret = select(socket_server + 1, &connectionfds, NULL, NULL, &timeout2);
if (ret <= 0){
break;
}
continue;
}
else{
break;
}
}
// use whole gathered data
....
Run Code Online (Sandbox Code Playgroud)
我上面代码的问题是,如果我将 select timeout 设置的时间很短,我不能保证接收到所有数据(因为有些服务器真的很慢),如果我将超时设置为很长的时间(5-10 秒) ),我的套接字长时间处于等待状态,在此之前我无法使用响应。我试图通过使用“BIO_should_read()”或“BIO_pending()”函数来完成这项工作,但它们都没有给我想要的东西。那么,有没有办法确定什么时候在 SSL 套接字上没有其他东西可以读取?
正如 Steffen 所说,SSL 和 TCP/IP 流中没有“数据结束”的概念。现代 http 服务器正在使用“保持活动”连接,并且在回答您的请求后不会断开连接。相反,他们正在使用您需要推断答案长度的其他信息。它要么是“Content-lenght”标头,要么使用“Transfer-Encoding:chunked”后跟数据块。每个块前面都有大小(作为十六进制数)。大小为零的块表示答案结束。
对您来说,获得可用内容的最简单方法可能是将请求作为 HTTP 1.0 请求(而不是 HTTP 1.1)发送。如果您发出这样的请求:
GET /myrequestdir/myrequestfile HTTP/1.0
Run Code Online (Sandbox Code Playgroud)
服务器将在回答您的请求后立即关闭连接。
如果您需要 HTTP 1.1,这里有两个示例,服务器如何用“你好”来回答。信息:
HTTP/1.1 200 OK
Content-Length:6
Hello.
Run Code Online (Sandbox Code Playgroud)
或使用分块连接:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
6
Hello.
0
Run Code Online (Sandbox Code Playgroud)