openssl之BIO系列之8---读写出错控制

读写出错控制

    ---根据openssl doc/crypto/bio/bio_should_retry.pod翻译和自己的理解写成

    (作者:DragonKing Mail:wzhah@263.net 发布于:http://gdwzh.126.com之open

ssl专业论坛)

    当BIO_read或BIO_write函数调用出错的时候,BIO本身提供了一组出错原因的诊断

函数,他们定义如下(openssl/bio.h):

     #define BIO_should_read(a) ((a)->flags & BIO_FLAGS_READ)

     #define BIO_should_write(a) ((a)->flags & BIO_FLAGS_WRITE)

     #define BIO_should_io_special(a) ((a)->flags & BIO_FLAGS_IO_SPECIAL)

     #define BIO_retry_type(a) ((a)->flags & BIO_FLAGS_RWS)

     #define BIO_should_retry(a) ((a)->flags & BIO_FLAGS_SHOULD_RETRY)

     #define BIO_FLAGS_READ 0x01

     #define BIO_FLAGS_WRITE 0x02

     #define BIO_FLAGS_IO_SPECIAL 0x04

     #define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPEC

IAL)

     #define BIO_FLAGS_SHOULD_RETRY 0x08

     BIO * BIO_get_retry_BIO(BIO *bio, int *reason);

     int BIO_get_retry_reason(BIO *bio);

    因为这些函数是用于决定为什么BIO在读写数据的时候不能读出或写入数据,所以他

们一般也是在执行BIO_read或BIO_write操作之后被调用的。

    【BIO_should_retry 】

    如果读写出错的情况是要求程序稍后重试,那么该函数返回true.如果该函数返回f

alse,这时候判定错误情况就要根据BIO的类型和BIO操作的返回值来确定了。比如,如

果对socket类型的BIO调用BIO_read操作并且返回值为0,此时BIO_should_retry返回fa

lse就说明socket连接已经关闭了。而如果是file类型的BIO出现这样的情况,那说明就

是读到文件eof了。有些类型BIO还会提供更多的出错信息,具体情况参见各自的说明。

 

    如果BIO下层I/O结构是阻塞模式的,那么几乎所有(SSL类型BIO例外)BIO类型都不

会返回重试的情况(就是说调用BIO_should_retry不会返回true),因为这时候对下层

I/O的调用根本不会进行。所以建议如果你的应用程序能够判定该类型BIO在执行IO操作

后不会出现重试的情况时,就不要调用BIO_should_retry函数。file类型BIO就是这样的

一个典型例子。

    SSL类型的BIO是上述规则的唯一例外,也就是说,既便在阻塞型的I/O结构中,如果

在调用BIO_read的时候发生了握手的过程,它也能会返回重试要求(调用BIO_should_r

etry返回true)。在这种情况下,应用程序可以立刻重新执行失败的I/O操作,或者在底

层的I/O结构中设置为SSL_MODE_AUTO_RETRY,那么就可以避免出现这种失败的情况。

    如果应用程序在非阻塞型BIO中调用IO操作失败后立刻重试,那么可能导致效率很低

,因为在数据允许读取或有效之前,调用会重复返回失败结果。所以,正常的应用应该

是等到需要的条件满足之后,程序才执行相关的调用,至于具体怎么做,就跟底层的IO

结构有关了。例如,如果一个底层IO是一个soket,并且BIO_should_retry返回true,那

么可以调用select()来等待数据有效之后再重试IO操作。在一个线程中,可以使用一个

select()来处理多个非阻塞型的BIO,不过,这时候执行效率可能出现非常低的情况,比

如如果其中一个延时很长的SSL类型BIO在握手的时候就会导致这种情况。

    在阻塞型的IO结构中,对数据的读取操作可能会导致无限期的阻塞,其情况跟系统

的IO结构函数有关。我们当然不期望出现这种情况,解决的办法之一是尽量使用非阻塞

型的IO结构和使用select函数(或equivalent)来设置等待时间。

    【BIO_should_read】

    该函数返回true如果导致IO操作失败的原因是BIO此时要读数据。

    【BIO_should_write】

    该函数返回true如果导致IO操作失败的原因是BIO此时要写数据。

    【BIO_should_io_special】

    该函数返回true如果导致IO操作失败的原因是特殊的(也就是读写之外的原因)

    【BIO_get_retry_reason】

    返回失败的原因,其代码包括BIO_FLAGS_READ, BIO_FLAGS_WRITE和BIO_FLAGS_IO_

SPECIAL。目前的BIO类型只返回其中之一。如果输入的BIO是产生特殊出错情况的BIO,

那么该函数返回错误的原因代码,就跟BIO_get_retry_BIO()返回的reason一样。

    【BIO_get_retry_BIO】

    该函数给出特殊情况错误的简短原因,它返回出错的BIO,如果reason不是设置为N

ULL,它会包含错误代码,错误码的含义以及下一步应该采取的处理措施应该根据发生这

种情况下各种BIO的类型而定。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值