我用阻塞模式的socket做ssl连接就能得到证书,但是用非阻塞的socket得到证书就为空。
下面是代码:
void ShowCerts(SSL * ssl) //show the certification
{
X509 * cert;
char * line;
cert = SSL_get_peer_certificate(ssl);
if (cert != NULL)
{
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("certification: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("publisher: %s\n", line);
free(line);
X509_free(cert);
}
else
{
printf("no certification!\n");
}
}
int main(int argc, char * *argv)
{
if (argc != 3)
{
printf("parameter error1!\n");
exit(0);
}
int sockfd, len;
struct sockaddr_in dest;
//initialize ssl
SSL_CTX * ctx;
SSL * ssl;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL)
{
ERR_print_errors_fp(stdout);
exit(1);
}
//create socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
exit(errno);
}
printf("socket created\n");
bzero( &dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[2]));
if (inet_aton(argv[1], (struct in_addr * ) &dest.sin_addr.s_addr) == 0)
{
perror(argv[1]);
exit(errno);
}
printf("address created\n");
int error=-1;
len = sizeof(int);
struct timeval tm;
fd_set set;
// set non-block socket
unsigned long ul = 1;
ioctl(sockfd,FIONBIO,&ul);
// create tcp connection
bool ret =false;
if (connect(sockfd, (struct sockaddr * ) &dest, sizeof(dest)) == -1)
{
tm.tv_sec =TIMEOUT;
tm.tv_usec = 0;
FD_ZERO(&set);
FD_SET(sockfd,&set);
if(select(sockfd+1,NULL,&set,NULL,&tm)>0)
{
getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,(socklen_t *)&len);
if(error==0)
{
ret = true; //connect successfully
}
else
{
ret = false; //connect timeout
}
}
else
{
ret = false;
}
}
else
{
ret = true;
}
if(!ret)
{
close(sockfd);
SSL_CTX_free(ctx);
printf("tcp connection timeout!\n");
exit(0);
}
printf("server connected\n");
ssl = SSL_new(ctx);
//bind socket and ssl
SSL_set_fd(ssl, sockfd);
int flag;
int result;
int ssl_conn_ret=0;
if(1!=ssl_conn_ret)
{
//non block ssl connection
ssl_conn_ret=SSL_connect(ssl);
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
int ssl_get_error_value = SSL_get_error(ssl,ssl_conn_ret);
printf("ssl_get_error_value is %d\n",ssl_get_error_value);
switch (ssl_get_error_value)
{
case SSL_ERROR_WANT_READ:
result=select(sockfd + 1, &fds, NULL, NULL, &tm);
if(0==result)
{
flag=0;
}
else if(-1==result)
{
flag=0;
}
else
{
flag=1; //connect successfully
}
break;
case SSL_ERROR_WANT_WRITE:
result=select(sockfd + 1, NULL, &fds, NULL, &tm);
if(0==result)
{
flag=0;
}
else if(-1==result)
{
flag=0; //conncet failed
}
else
{
flag=1;
}
break;
default:
flag=0;
break;
}
}
if(0==flag)
{
printf("connection error!\n");
}
if(1==ssl_conn_ret||1==flag)
{
ShowCerts(ssl);
}
ul = 0;
ioctl(sockfd, FIONBIO, &ul);
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return 0;
}