Sockets SSL_accept()失败,返回值为-1
为了理解Sockets SSL_accept()失败,返回值为-1,sockets,tcp,openssl,Sockets,Tcp,Openssl,为了理解SSL/TLS,我在Windows-7上下载了OpenSSL-1.0.2k,并使用Cygwingcc64位编译器进行编译。我从gcc中获取了服务器/客户端的示例,并使用cygwin-gcc进行编译。编译一开始就成功了。我使用以下命令从cmd执行服务器和客户端 (Server) D:\>ssl-server.exe 5000 (Client) D:\>ssl-client.exe 127.0.0.1 5000 客户端退出时没有任何响应,但另一方面,服务器显示它已建立连
SSL/TLS
,我在Windows-7
上下载了OpenSSL-1.0.2k
,并使用Cygwin
gcc64位
编译器进行编译。我从gcc中获取了服务器/客户端的示例,并使用cygwin-gcc
进行编译。编译一开始就成功了。我使用以下命令从cmd
执行服务器和客户端
(Server) D:\>ssl-server.exe 5000
(Client) D:\>ssl-client.exe 127.0.0.1 5000
客户端退出时没有任何响应,但另一方面,服务器显示它已建立连接,例如
Connection: 127.0.0.1:50475
无限期地等待下一行
然后我开始调试服务器端,发现过程void Servlet(SSL*SSL)
中的SSL\u accept()
返回一个值-1
,这是不期望的。我查阅了OpenSSL
的文档
TLS/SSL握手未成功,因为在协议级别发生致命错误或发生连接故障。关闭不干净。如果需要继续非阻塞BIOs的操作,也可能会发生这种情况。使用返回值ret调用SSL_get_error()以查找原因
SSL\u get\u error()
返回SSL\u error\u SYSCALL
。在这次调用之后,我检查了errno
的值,发现no error
。下面是Servlet
方法的完整代码。代码的其余部分和链接中的相同
void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{ char buf[1024];
char reply[1024];
int sd, bytes;
const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n";
int ret;
ret = SSL_accept(ssl); /* do SSL-protocol accept */
if ( ret == -1 )
{
// printf(" SSL_accept() returned -1\n");
switch(SSL_get_error(ssl, ret) )
{
case SSL_ERROR_SYSCALL:
perror("errno");
break;
default:
printf( "default" );
break;
}
exit(-1);
}
else if ( ret == 0)
{
printf(" SSL_accept() returned 0\n");
exit(-1);
}
else if ( ret == 1) // The TLS/SSL connection has been established.
{
ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
if ( bytes > 0 )
{
buf[bytes] = 0;
printf("Client msg: \"%s\"\n", buf);
sprintf(reply, HTMLecho, buf); /* construct reply */
SSL_write(ssl, reply, strlen(reply)); /* send reply */
}
else
ERR_print_errors_fp(stderr);
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
void Servlet(SSL*SSL)/*为连接提供服务--可线程化*/
{char buf[1024];
字符回复[1024];
int-sd,字节;
常量char*HTMLecho=“%s\n\n”;
int ret;
ret=SSL_接受(SSL);/*SSL协议接受吗*/
如果(ret==-1)
{
//printf(“SSL_accept()返回-1\n”);
交换机(SSL_获取_错误(SSL,ret))
{
案例SSL\u错误\u系统调用:
佩罗尔(“埃尔诺”);
打破
违约:
printf(“违约”);
打破
}
出口(-1);
}
else if(ret==0)
{
printf(“SSL_accept()返回0\n”);
出口(-1);
}
else if(ret==1)//已建立TLS/SSL连接。
{
ShowCerts(ssl);/*获取任何证书*/
bytes=SSL_read(SSL,buf,sizeof(buf));/*get请求*/
如果(字节>0)
{
buf[字节]=0;
printf(“客户端消息:\%s\”\n),buf);
sprintf(reply,HTMLecho,buf);/*构造reply*/
SSL_write(SSL,reply,strlen(reply));/*发送回复*/
}
其他的
错误打印错误fp(stderr);
}
sd=SSL_get_fd(SSL);/*获取套接字连接*/
无SSL(SSL);/*释放SSL状态*/
关闭(sd);/*关闭连接*/
}
当您没有遇到您列举的SSL\u错误情况时,您应该跟踪SSL\u get\u ERROR()
的值,以便开始调试。而不仅仅是举手
在本例中,值为SSL\u ERROR\u SYSCALL
。你没有在你认为应该的地方抓住它,因为case(SSL_ERROR|u SYSCALL | SSL_ERROR_SSL | SSL_ERROR_WANT_CONNECT | SSL_ERROR_WANT_ACCEPT):
没有按照你的想法去做。由于|
的语义,它将变成情况1
。每个值都应该有单独的case
语句
SSL\u ERROR\u SYSCALL
表示根据您自己引用的文档,基本错误在errno
中,这意味着您应该跟踪该错误。而不仅仅是举手。请注意,您必须在调用任何其他系统调用(例如通过printf()
调用write()
)之前执行此操作,以便立即保存errno
您可以使用printf(“errno=%d\n”,errno)
直接打印errno
,但打印错误消息更有用,您可以使用peror()
或printf(“error=%s\n”,strerror(errno))
SSL\u get\u error()
的值不是errno
值,也不是您开始使用的原始-1。errno
值来自errno
变量
但是,除非SSL\u accept()
返回了-1,否则不应该执行这些操作,这里没有实际的证据
所以这里完全可能没有错误
当您没有遇到您列举的SSL\u错误情况时,您应该跟踪SSL\u get\u ERROR()
的值,以便开始调试。而不仅仅是举手
在本例中,值为SSL\u ERROR\u SYSCALL
。你没有在你认为应该的地方抓住它,因为case(SSL_ERROR|u SYSCALL | SSL_ERROR_SSL | SSL_ERROR_WANT_CONNECT | SSL_ERROR_WANT_ACCEPT):
没有按照你的想法去做。由于|
的语义,它将变成情况1
。每个值都应该有单独的case
语句
SSL\u ERROR\u SYSCALL
表示根据您自己引用的文档,基本错误在errno
中,这意味着您应该跟踪该错误。而不仅仅是举手。请注意,您必须在调用任何其他系统调用(例如通过printf()
调用write()
)之前执行此操作,以便立即保存errno
您可以使用printf(“errno=%d\n”,errno)
直接打印errno
,但打印错误消息更有用,您可以使用peror()
或printf(“error=%s\n”,strerror(errno))
SSL\u get\u error()
的值不是errno
值,也不是您开始使用的原始-1。一个错误