OpenSSL 非阻塞套接字 SSL_read() 不可预测
OpenSSL Non-Blocking Socket SSL_read() unpredictable
我正在尝试创建一个非阻塞套接字 w/OpenSSL 以便我可以循环 SSL_read() 直到没有更多数据剩余,然后中断循环。经过大量工作,我终于让连接正常工作,但现在对于前一千次迭代 SSL_read() 将 return -1。之后,它会给我套接字上的实际数据。 SSL_read() 也没有 return 读取准确的字节数,它总是说 -1,即使它正在读取正确的字节。我能够让它完美地工作 w/blocking 套接字但非阻塞似乎有问题...
char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int r;
int received = -1, count = 0;
int TotalReceived = 0, ReallocSize = 0;
char buffer[1024];
if (c)
{
while (1)
{
received = SSL_read (c->sslHandle, buffer, readSize);
buffer[received] = '[=11=]';
TotalReceived += received;
printf("Buffsize - %i - %s \n", received, buffer);
if (received <= 0)
{
// this line added per advice of Eric Tsui but does not
// change behaviour
received = SSL_read (c->sslHandle, buffer, readSize);
//printf(" received equal to or less than 0\n")
switch (SSL_get_error(c->sslHandle, received))
{
case SSL_ERROR_NONE:
{
printf("SSL_ERROR_NONE %i\n", count);
//if (received != -1)
// goto END;
break;
}
case SSL_ERROR_ZERO_RETURN:
{
printf("SSL_ERROR_ZERO_RETURN %i\n", count);
goto END;
break;
}
case SSL_ERROR_WANT_READ:
{
printf("SSL_ERROR_WANT_READ %i\n", count);
break;
}
case SSL_ERROR_WANT_WRITE:
{
printf("SSL_ERROR_WANT_WRITE %i\n", count);
goto END;
//break;
}
default:
{
printf("error %i\n", received);
break;
}
}
count++;
}
}
}
END:
return rc;
}
如果您以前这样做过,如果您能告诉我这段代码有什么问题,我将不胜感激。谢谢
您的循环调用 SSL_read()
的次数过多,并且当确实没有更多数据可读取时(SSL_ERROR_WANT_READ
条件),您的错误处理并未中断循环。尝试更像这样的东西:
char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int received, count = 0;
int TotalReceived = 0;
fd_set fds;
struct timeval timeout;
char buffer[1024];
if (c)
{
while (1)
{
received = SSL_read (c->sslHandle, buffer, readSize);
if (received > 0)
{
TotalReceived += received;
printf("Buffsize - %i - %.*s \n", received, received, buffer);
}
else
{
count++;
//printf(" received equal to or less than 0\n")
int err = SSL_get_error(c->sslHandle, received);
switch (err)
{
case SSL_ERROR_NONE:
{
// no real error, just try again...
printf("SSL_ERROR_NONE %i\n", count);
continue;
}
case SSL_ERROR_ZERO_RETURN:
{
// peer disconnected...
printf("SSL_ERROR_ZERO_RETURN %i\n", count);
break;
}
case SSL_ERROR_WANT_READ:
{
// no data available right now, wait a few seconds in case new data arrives...
printf("SSL_ERROR_WANT_READ %i\n", count);
int sock = SSL_get_rfd(c->sslHandle);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 5;
timeou.tv_nsec = 0;
err = select(sock+1, &fds, NULL, NULL, &timeout);
if (err > 0)
continue; // more data to read...
if (err == 0) {
// timeout...
} else {
// error...
}
break;
}
case SSL_ERROR_WANT_WRITE:
{
// socket not writable right now, wait a few seconds and try again...
printf("SSL_ERROR_WANT_WRITE %i\n", count);
int sock = SSL_get_wfd(c->sslHandle);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 5;
timeou.tv_nsec = 0;
err = select(sock+1, NULL, &fds, NULL, &timeout);
if (err > 0)
continue; // can write more data now...
if (err == 0) {
// timeout...
} else {
// error...
}
break;
}
default:
{
printf("error %i:%i\n", received, err);
break;
}
}
break;
}
}
}
return rc;
}
我正在尝试创建一个非阻塞套接字 w/OpenSSL 以便我可以循环 SSL_read() 直到没有更多数据剩余,然后中断循环。经过大量工作,我终于让连接正常工作,但现在对于前一千次迭代 SSL_read() 将 return -1。之后,它会给我套接字上的实际数据。 SSL_read() 也没有 return 读取准确的字节数,它总是说 -1,即使它正在读取正确的字节。我能够让它完美地工作 w/blocking 套接字但非阻塞似乎有问题...
char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int r;
int received = -1, count = 0;
int TotalReceived = 0, ReallocSize = 0;
char buffer[1024];
if (c)
{
while (1)
{
received = SSL_read (c->sslHandle, buffer, readSize);
buffer[received] = '[=11=]';
TotalReceived += received;
printf("Buffsize - %i - %s \n", received, buffer);
if (received <= 0)
{
// this line added per advice of Eric Tsui but does not
// change behaviour
received = SSL_read (c->sslHandle, buffer, readSize);
//printf(" received equal to or less than 0\n")
switch (SSL_get_error(c->sslHandle, received))
{
case SSL_ERROR_NONE:
{
printf("SSL_ERROR_NONE %i\n", count);
//if (received != -1)
// goto END;
break;
}
case SSL_ERROR_ZERO_RETURN:
{
printf("SSL_ERROR_ZERO_RETURN %i\n", count);
goto END;
break;
}
case SSL_ERROR_WANT_READ:
{
printf("SSL_ERROR_WANT_READ %i\n", count);
break;
}
case SSL_ERROR_WANT_WRITE:
{
printf("SSL_ERROR_WANT_WRITE %i\n", count);
goto END;
//break;
}
default:
{
printf("error %i\n", received);
break;
}
}
count++;
}
}
}
END:
return rc;
}
如果您以前这样做过,如果您能告诉我这段代码有什么问题,我将不胜感激。谢谢
您的循环调用 SSL_read()
的次数过多,并且当确实没有更多数据可读取时(SSL_ERROR_WANT_READ
条件),您的错误处理并未中断循环。尝试更像这样的东西:
char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int received, count = 0;
int TotalReceived = 0;
fd_set fds;
struct timeval timeout;
char buffer[1024];
if (c)
{
while (1)
{
received = SSL_read (c->sslHandle, buffer, readSize);
if (received > 0)
{
TotalReceived += received;
printf("Buffsize - %i - %.*s \n", received, received, buffer);
}
else
{
count++;
//printf(" received equal to or less than 0\n")
int err = SSL_get_error(c->sslHandle, received);
switch (err)
{
case SSL_ERROR_NONE:
{
// no real error, just try again...
printf("SSL_ERROR_NONE %i\n", count);
continue;
}
case SSL_ERROR_ZERO_RETURN:
{
// peer disconnected...
printf("SSL_ERROR_ZERO_RETURN %i\n", count);
break;
}
case SSL_ERROR_WANT_READ:
{
// no data available right now, wait a few seconds in case new data arrives...
printf("SSL_ERROR_WANT_READ %i\n", count);
int sock = SSL_get_rfd(c->sslHandle);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 5;
timeou.tv_nsec = 0;
err = select(sock+1, &fds, NULL, NULL, &timeout);
if (err > 0)
continue; // more data to read...
if (err == 0) {
// timeout...
} else {
// error...
}
break;
}
case SSL_ERROR_WANT_WRITE:
{
// socket not writable right now, wait a few seconds and try again...
printf("SSL_ERROR_WANT_WRITE %i\n", count);
int sock = SSL_get_wfd(c->sslHandle);
FD_ZERO(&fds);
FD_SET(sock, &fds);
timeout.tv_sec = 5;
timeou.tv_nsec = 0;
err = select(sock+1, NULL, &fds, NULL, &timeout);
if (err > 0)
continue; // can write more data now...
if (err == 0) {
// timeout...
} else {
// error...
}
break;
}
default:
{
printf("error %i:%i\n", received, err);
break;
}
}
break;
}
}
}
return rc;
}