previous question询问是否更改了一行代码实现了持久性SSL连接。在看到该问题的回答并检查缺少SSL文档后,以下情况似乎是正确的:
对于服务器,持久连接只是在SSL_accept()和SSL_set_shutdown()之间进行重复的请求/响应。
根据this page,客户必须通过发送相应的“Content-length:”标头或使用商定的终止请求来指示将有多少请求。
< / LI>然而,无法保证客户端会发送它应该发送的内容。因此,似乎使用阻塞套接字的服务器可以无限期地挂起在SSL_read()上,同时等待从未到达的其他请求。 (SSL_CTX_set_timeout()似乎不会导致后续的SSL_read()提前退出,因此如果套接字阻塞,则不清楚如何this Wikipedia page所述的超时连接。)
显然,服务器可以通过返回带有响应的“Connection:Close”标头来指示它不会保持活动状态,所以我最终得到了以下代码,至少应该始终正确地执行单个每个连接的请求/响应:
while TRUE do
begin // wait for incoming TCP connection
if notzero(listen(listen_socket, 100)) then continue; // listen failed
client_len := SizeOf(sa_cli);
sock := accept(listen_socket, @sa_cli, @client_len); // create socket for connection
if sock = INVALID_SOCKET then continue; // accept failed
ssl := SSL_new(ctx); // TCP connection ready, create ssl structure
if assigned(ssl) then
begin
SSL_set_fd(ssl, sock); // assign socket to ssl structure
if SSL_accept(ssl) = 1 then // handshake worked
begin
request := '';
repeat // gather request
bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
if bytesin > 0 then
begin
buffer[bytesin] := #0;
request := request + buffer;
end;
until SSL_pending(ssl) <= 0;
if notempty(request) then
begin // decide on response, avoid keep-alive
response := 'HTTP/1.0 200 OK'#13#10'Connection: Close'#13#10 + etc;
SSL_write(ssl, pchar(response)^, length(response));
end; // else read empty or failed
end; // else handshake failed
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN or SSL_RECEIVED_SHUTDOWN);
CloseSocket(sock);
SSL_free(ssl);
end; // else ssl creation failed
end; // infinite while
两个问题:
(1)由于SSL_accept()必须为true才能到达SSL_read(),是否真的SSL_read()永远不会挂起等待第一个请求?
(2)如何修改此代码以使用阻塞套接字执行超时持久/保持活动的SSL连接(如果可能的话)?
答案 0 :(得分:1)
引用this letter,“确保避免无限期阻塞的唯一方法是使用非阻塞I / O.”所以,我想我会放弃尝试超时阻止SSL_read()s。
答案 1 :(得分:0)
(1)如果客户端连接但未发送请求(例如,DoS攻击),则SSL_read()将挂起。
(2)尝试在接受的setsockopt(SO_RCVTIMEO)
上调用SOCKET
来设置读取超时。