OpenSSL과 select
소켓 통신할 때 시간초과(time out) 처리를 위해 아래와 같이 select 시스템콜을 쓰는 경우가 많다.
fd_set rset;
FD_ZERO(&rset);
FD_SET(fd, &rset);
n = select(fd + 1, &rset, NULL, NULL, &t);
if (n < 0)
/* 오류 처리 */
else if (n == 0)
/* 시간 초과 */
n = read(fd, buf, sizeof(buf));
일반적인 소켓이 아니라 OpenSSL의 BIO을 사용한다면 아래와 같이 하면 된다.
BIO_set_nbio(bio, 1); // non-block socket으로 설정
int num_read = 0;
while ( num_read < size ) {
int n = BIO_read( bio, buf + num_read, size - num_read );
if ( n > 0 ) {
num_read += n;
continue;
}
if ( !BIO_should_retry( bio ) ) {
return -1;
}
fd_set rset;
FD_ZERO(&rset);
fd_set wset;
FD_ZERO(&wset);
if (BIO_should_read(bio)) {
FD_SET(fd, &rset);
} else if (BIO_should_write(bio)) {
FD_SET(fd, &wset);
} else {
return -1;
}
n = select(fd + 1, &rset, &wset, NULL, &t);
if (n <= 0) {
if (n < 0) {
return -1;
} else {
printf("select timed out");
}
}
}