此代码适用于使用阻塞套接字的HTTPS服务器:
request := '';
start := gettickcount;
repeat
if SSL_pending(ssl) > 0 then
begin
bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
if bytesin > 0 then
begin
buffer[bytesin] := #0;
request := request + buffer;
end
else break; // read failed
end; // pending
until (gettickcount - start) > LARGETIMEOUT;
// "request" is ready, though possibly empty
SSL_pending()始终返回零,并且永远不会达到SSL_read()。如果删除了SSL_pending()调用,则执行SSL_read()。为什么SSL_pending()不指示可用的字节数?
请注意,如果您调用SSL_read()并且返回的字节数小于缓冲区大小,那么您已阅读所有内容并已完成。
如果传入的数据大于缓冲区大小,则第一个SSL_read()调用将填充缓冲区,您可以重复调用SSL_read(),直到无法填充缓冲区为止。
BUT 如果传入的数据是缓冲区大小的精确倍数,则最后一块数据填充缓冲区。如果您尝试另一个SSL_read()认为阻塞套接字上可能有更多数据,它会无限期挂起。因此,首先要检查SSL_pending()。然而,这似乎不起作用。
如何避免挂在最终的SSL_read()上? (我无法想象答案是非阻塞,因为这意味着你永远不能将SSL_read与阻塞一起使用。)
更新:以下有效。显然SSL_pending()在第一个SSL_read()之后才起作用:
request := '';
repeat
bytesin := SSL_read(ssl, buffer, sizeof(buffer)-1);
if bytesin > 0 then
begin
buffer[bytesin] := #0;
request := request + buffer;
end
else break; // read failed
until SSL_pending(ssl) <= 0;
// "request" is ready, though possibly empty
答案 0 :(得分:6)
您正在以完全错误的方式使用SSL_pending()
。 OpenSSL使用状态机,其中SSL_pending()
指示状态机是否有任何已缓冲且正在等待处理的待处理字节。由于您永远不会调用SSL_read()
,因此您永远不会缓冲任何数据或推进状态机。
答案 1 :(得分:2)
如果SSL_pending函数返回的返回码为0,则并不一定意味着SSL会话上没有可立即读取的数据。返回码0表示当前SSL数据记录中没有更多数据。但是,可能已从网络接收到更多SSL数据记录。如果SSL_pending函数返回0的返回码,则发出select函数,传递套接字的文件描述符以检查套接字是否可读。可读意味着已从套接字上的网络接收到更多数据。