SSL_read返回SSL_ERROR_WANT_READ怎么办?

SSL_read返回SSL_ERROR_WANT_READ怎么办?

对SSL_read返回SSL_ERROR_WANT_READ的实践、理解和处理

在openssl使用编程中遇到问题,代码片段是这样的:
ret=SSL_read(ssl, line, sizeof (line));
err=SSL_get_error(ssl,ret); //观察返回值的情况,err=2时ret=-1, err=0时l=实际读取字节数
返回err=SSL_ERROR_WANT_READ时即err=2;
SSL_ERROR_WANT_READ的宏定义值就是2
那后续怎么处理呢?有人说在对ssl读之前要设一个超时,这是一种方法;但我经过实践,与其设置超时,不如直接多次重复读取一段时间,看看到底
是不是要延迟读取才有数据,但结果是重复无数次也是得不到任何数据。
这可以联想到,其实这并不是对端真正有延迟发送数据的情况,而是可能对端根本就是忘记发送后续数据了,只是本地认为需要继续读取数据而已,这
应该是对端程序的一个bug。
那我们本地处理的话,直接把它做为出错处理、退出就行。
举个例子,其中的注释就是实践总结的经验:
int ssl_recv(SSL_CTX *ctx, SSL **in_ssl, int cli_sock, char *buf, size_t len)
//这是一个收到客户端发送握手数据时的处理
{
…//ssl初始化
for(;?{
if (!SSL_is_init_finished(ssl)){
r=SSL_do_handshake(ssl);
if(r<=0)break;
printff(1,“SSL握手成功!恭喜你!\n”);
//正式通信读写数据 start
char line[4096]={0};
begin_recv:
l=SSL_read(ssl, line, sizeof (line));
err=SSL_get_error(ssl,l); //观察返回值的情况,err=2时l=-1, err=0时l=实际读取字节数, err=6时l=0这是当外部/客户端退出关闭套接字后的情况
//当客户端执行SSL_shutdown(ssl);时,这里会收到err=6时l=0,表示对方已关闭连接。实际上BIO_read()会收到31个字节。
if(l<=0){//continue; //这里应该直接跳出,重新进行握手吧;经测试,是的,从头(外部异步如iocp接收数据)重新来过。
//如果没接收到数据,则关闭返回(意思是重来);研究发现有的浏览器像chrome与服务器要进行SSL握手3次才进行通信,有的像firefox一次就行
}else{
printff(1,"%s",line); //for debugging
//如果接收到数据成功,则发送回复数据
char tmpbuf[1024]={0};
strcpy(tmpbuf,“HTTP/1.1 200 OK\r\n\r\n”);l=strlen(tmpbuf); //由HTTP/1.0改为HTTP/1.1
SSL_write(ssl,tmpbuf,l);
strcpy(tmpbuf,“Hello World”);l=strlen(tmpbuf);
SSL_write(ssl,tmpbuf,l);
}
//如果这里执行 if(err==2)goto begin_recv; 时,会无限循环,这不可取;本来客户端没有再理会了,你一直循环接收也没用了;直接关闭退出!
SSL_shutdown(ssl);
SSL_free(ssl);
closesocket(cli_sock);
return 0;
//正式通信读写数据 end
}
}
printff(1,“收到%d个加密数据,返回%d\n”,len,r);
return r; //返回值还没什么用
}
这个例子经过不同浏览器的测试,还有经过自己编的客户端程序的测试都很顺利通过,没有卡顿现象。
证明把SSL_read返回SSL_ERROR_WANT_READ时当成出错退出处理是对的。
此文结束!

你可能感兴趣的:(SSL_read返回SSL_ERROR_WANT_READ怎么办?)