我必须使用SSL连接到某个服务器,其中包含URL主机/ getdata?reqtype = generate& login = xxx& pass = xxx& dest = yyy。
我正在使用下面显示的代码段,但我无法从服务器获取任何数据。
CRYPTO_malloc_init();
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
SSL* ssl;
BIO* bio = BIO_new_ssl_connect(ctx);
char *host = "host:8888";
char *con_protocol = "";
const char *REQUEST_PROTO = "GET /getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy HTTP/1.1\nHost: %s\nAccept: */*\nConnection: keep-alive\n\n";
char *con_string = (char*)calloc((strlen(host)+strlen(con_protocol))+1, sizeof(char));
strcat(con_string, host);
strcat(con_string, con_protocol);
// Failure?
if (bio == NULL) {
printf("Error creating BIO!\n");
ERR_print_errors_fp(stderr);
// We need to free up the SSL_CTX before we leave.
SSL_CTX_free(ctx);
return;
}
// Makes ssl point to bio's SSL object.
BIO_get_ssl(bio, &ssl);
// Set the SSL to automatically retry on failure.
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
printf("connection string : %s\n", con_string);
BIO_set_conn_hostname(bio, con_string);
// Same as before, try to connect.
int y = BIO_do_connect(bio);
if (y <= 0) {
printf("Failed to connect!\nError code : %d\n", y);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return;
}
// Now we need to do the SSL handshake, so we can communicate.
if (BIO_do_handshake(bio) <= 0) {
printf("Failed to do SSL handshake!\n");
BIO_free_all(bio);
SSL_CTX_free(ctx);
return;
}
// Create a buffer for grabbing information from the page.
char buf[1024];
memset(buf, 0, sizeof(buf));
// Create a buffer for the reqest we'll send to the server
char send[1024];
memset(send, 0, sizeof(send));
size_t total_size = strlen(REQUEST_PROTO)+strlen(host);
int t_size = (int)total_size+1;
char *my_buf = malloc(t_size*sizeof(char));
snprintf(my_buf, t_size, REQUEST_PROTO, host);
printf("my_buf : %s\n", my_buf);
BIO_puts(bio, my_buf);
int temp = 0;
int begin = 0;
char *key_buff = (char *)calloc(32, sizeof(char));
while (1) {
int bytes_read = BIO_read(bio, buf, sizeof(buf) - 1);
printf("bytes_read == %d\n", bytes_read);
if (bytes_read == 0) {
break;
}
else if (bytes_read < 0) {
if (!BIO_should_retry(bio)) {
printf("\nRead Failed!\n");
BIO_free_all(bio);
SSL_CTX_free(ctx);
return;
}
}
// We actually got some data, without errors!
else {
// Null-terminate our buffer, just in case
buf[bytes_read] = 0;
if ((bytes_read != 0) && (temp)) {
for (begin; begin<(bytes_read+begin); begin++) {
key_buff[begin] = buf[begin];
}
}
if (!temp) {
temp = bytes_read;
}
}
}
BIO_free_all(bio);
SSL_CTX_free(ctx);
printf("key : %s\n\n", buf);
我已检查过与CURL的连接。
使用命令时
curl --insecure 'https://localhost:8888/getdata?reqtype=generate&login=xxx&pass=xxx&dest=yyy'
一切正常,但当我从命令中删除'http'时,我得到了应用程序中的空响应。不幸的是我不能在BIO_set_conn_hostname()函数中添加'http'。
有些想法有什么不对?
答案 0 :(得分:2)
Duskwuff是对的,因为你显然通过https连接,你可以更容易地使用更高级别的东西作为cURL(你可以使用libcurl以编程方式使用它)。否则,您必须自己处理协议的HTTP部分。
如果这对您来说是可以接受的,那么我认为问题在于您的BIO没有缓冲,这就是为什么您不使用BIO_puts从服务器获取任何数据的原因。另见这篇优秀的turorial:
如果创建并设置了缓冲区BIO,则可以通过调用BIO_puts()和BIO_gets()以及BIO_write()和BIO_read(),来传输数据,而不是使用SSL_write()和SSL_read()。如下:...
使用两个BIO(一个用于SSL,一个用于缓冲)可以解决您的问题。