openssl之BIO系列之8

读写出错控制

—根据openssldoc/crypto/bio/bio_should_retry.pod翻译和自己的理解写成

(作者:DragonKingMail:wzhah@263.net发布于:之open

ssl专业论坛)

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

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

#defineBIO_should_read(a)((a)->flags&BIO_FLAGS_READ)

#defineBIO_should_write(a)((a)->flags&BIO_FLAGS_WRITE)

#defineBIO_should_io_special(a)((a)->flags&BIO_FLAGS_IO_SPECIAL)

#defineBIO_retry_type(a)((a)->flags&BIO_FLAGS_RWS)

#defineBIO_should_retry(a)((a)->flags&BIO_FLAGS_SHOULD_RETRY)

#defineBIO_FLAGS_READ0x01

#defineBIO_FLAGS_WRITE0x02

#defineBIO_FLAGS_IO_SPECIAL0x04

#defineBIO_FLAGS_RWS(BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPEC

IAL)

#defineBIO_FLAGS_SHOULD_RETRY0x08

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

intBIO_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的类型而定。

充满了恐惧的声音,一种不确定的归宿的流动。

openssl之BIO系列之8

相关文章:

你感兴趣的文章:

标签云: