我有一个非阻塞套接字,并使用select处理来自多个SSL客户端的连接:
我已经尝试过有关处理SSL_ERROR_WANT_READ的建议,例如重复SSL_read调用,或者返回到Select,但是对于我来说似乎不起作用。
while (1)
{
start:
if (readyCount = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout) < 0)
{
exit(EXIT_FAILURE);
}
for (int i = 0; i < FD_SETSIZE; ++i)
if (FD_ISSET(i, &read_fd_set))
{
if (i == sockfd)
{
newSocket = accept(sockfd, (struct sockaddr *) &clientname, (socklen_t*)&size);
}
else
{
ssl = SSL_new(ctx);
SSL_set_fd(ssl, i);
accept:
int err = SSL_accept(ssl);
if (0 >= err)
{ // it never goes here
int resultCode = SSL_get_error(ssl, err);
switch (resultCode)
{
case SSL_ERROR_NONE:
goto accept;
break;
case SSL_ERROR_ZERO_RETURN:
SSL_shutdown(ssl);
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_WRITE:
break;
case SSL_ERROR_WANT_CONNECT:
break;
case SSL_ERROR_WANT_ACCEPT:
goto accept;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
break;
case SSL_ERROR_SSL:
break; }
default:
break;
}
}
else
{
Call_Read(...)
}
SSL_free(ssl);
close(i);
FD_CLR(i, &active_fd_set);
}
}
}
Call_Read(...)
{
int fd = SSL_get_fd(ssl);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
while (data_size > 0)
{
bytes_recv = SSL_read(ssl, data, data_size);
if (bytes_recv <= 0)
{
if (SSL_ERROR_WANT_READ == SSL_get_error(ssl, bytes_recv))
{
testtt = SSL_pending(ssl); //always 0
/*SSL_renegotiate(ssl);
SSL_do_handshake(ssl);*/
continue;
}
if (SSL_ERROR_WANT_WRITE == SSL_get_error(ssl, bytes_recv))
{
testtt = SSL_pending(ssl);
int blocked_on_SSL_ERROR_WANT_WRITE = 1;
continue; }
}
return bytes_recv;
}
data += bytes_recv;
data_size -= bytes_recv;
}
return 1;
}
Client Write:
{
while (data_size > 0)
{
bytes_sent = SSL_write(ssl, data_ptr, data_size);
if (errno == EPIPE) == doesn’t reach this line, debugger stops with EPIPE
{
printf("WRITE socket returned EPIPE”);
return -1;
}
if (bytes_sent < 0)
{
int err = SSL_get_error(ssl, bytes_sent);
switch (err)
{
case SSL_ERROR_WANT_READ:
printf(" SSL_ERROR_WANT_READ\n");
case SSL_ERROR_WANT_WRITE:
printf(" SSL_ERROR_WANT_WRITE\n");
default:
;
}
}
data_ptr += bytes_sent;
data_size -= bytes_sent;
}
return 1;
}
当服务器处于SSL_Read且某些客户端调用SSL_Connect时,我不知道该如何处理。
在这种情况下,对于SSL_ERROR_WANT_READ,Call_Read将处于无限循环中。如果我将“ continue”语句替换为将结束循环的标志,并且调用者返回“ Select”,则客户端将因管道错误而中断,甚至不会到达“ WRITE socket returned EPIPE”行。如果我从读取循环返回到Accept而不是Select,也会发生同样的情况。
我在这里缺少一些东西,我想知道是否也应该对客户端进行一些更改。 有什么建议吗?