C语言接入openssl,实现https请求客户端

    科技2025-08-30  4

    更新了

    //gcc -fPIC -shared -o libhttps.so https.c -lssl -lcrypto //gcc -o https https.c -lssl -lcrypto #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <errno.h> #include <sys/socket.h> #include <resolv.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <assert.h> #include <netdb.h> #include <openssl/ssl.h> #include <openssl/err.h> void download(const char *buf); int main() { char buf[] = "https://img.tupianzj.com/uploads/allimg/202006/9999/c7fad5556a.jpg"; download(buf); return 0; } void download(const char *buf) { if(!buf) { return ; } printf("%s\n",buf); char host[64] = {0}; char url[128] = {0}; char ip[16] = {0}; char obj[64] = {0}; char *ret; int buf_len = strlen(buf); ret = strstr(buf,"https"); if(!ret){ fprintf(stderr,"need https"); return ; } ret = strstr(buf,"//"); if(!ret){ fprintf(stderr,"error //"); return ; } char *end = strstr(ret+2, "/"); if(!end){ fprintf(stderr,"error /"); return ; } assert(sizeof(host) > end-ret-2); strncpy(host, ret+2, end-ret-2); struct hostent *hostinfo = gethostbyname(host); if(!hostinfo) { fprintf(stderr,"hostinfo /"); return ; } //memcpy(ip, hostinfo->h_addr, 4);//32位ip地址=4字节 structaddr strcpy(ip,inet_ntoa( *(struct in_addr*)hostinfo->h_addr_list[0] )); assert(sizeof(url) > strlen(end+1)); strcpy(url,end+1); //printf("%s\n",host); //printf("%s\n",url); //printf("%s\n",ip); time_t now ; struct tm *tm_now; time(&now) ; tm_now = localtime(&now) ; end = (char*)buf + strlen(buf)-5; sprintf(obj,"%d-%02d-%02d %02d:%02d:%02d_%s",tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, end ); //printf("%s\n",obj); int sockfd, len; struct sockaddr_in dest; char buffer[1024]; SSL_CTX *ctx; SSL *ssl; int port = 443; /* 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); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket Create Fail!"); exit(errno); } /* 建立 TCP 连接 */ bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(port); if (inet_aton(ip, (struct in_addr *) &dest.sin_addr.s_addr) == 0) { perror("Socket Init Fail!"); exit(errno); } if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { perror("Socket Connect Fail!"); exit(errno); } printf("%s connect ok\n",ip); /* 绑定 Socket 与 SSL */ ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); /* 建立 SSL 连接 */ if (SSL_connect(ssl) == -1) { ERR_print_errors_fp(stderr); return ; } else{ printf("SSL Connected with %s encryption\n", SSL_get_cipher(ssl)); } sprintf(buffer, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Close\r\n\r\n", url, host); printf("\n%s\n",buffer); /* SSL 发数据 */ len = SSL_write(ssl, buffer, strlen(buffer)); if (len < 0) { printf("SSL Send failure! errno = %d, err_msg = %s\n", errno, strerror(errno)); return ; } bzero(buffer, 1024); int nbytes; /* SSL 收数据 */ //read header char header[128] = {0}; //保存response第一行 int i=0; int is_end = 0; char ch; while ((nbytes = SSL_read(ssl, &ch, 1)) == 1) { printf("%c",ch); if(!is_end) { header[i++] = ch; } if (ch=='\r') { nbytes = SSL_read(ssl, &ch, 1); printf("%c",ch); if(!is_end) { header[i++] = ch; is_end=1; } if (nbytes>0 && ch=='\n') { nbytes = SSL_read(ssl, &ch, 1); printf("%c",ch); if (nbytes>0 && ch=='\r') { nbytes = SSL_read(ssl, &ch, 1); //header[i++] = ch; printf("%c",ch); if (nbytes>0 && ch=='\n') { break; } } } } } //printf("%s\n", header); if(!strstr(header,"200 OK")){ fprintf(stderr,"response error"); return ; } FILE *fp = fopen(obj,"wb"); assert(fp); //read body int body_len = 0; while ((nbytes = SSL_read(ssl, buffer, 1024)) > 0) { body_len += nbytes; fwrite(buffer,nbytes,1,fp); } fclose(fp); printf("body_len %d\n",body_len); /* 关闭连接 */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); } /* gcc -c -fPIC test.c -o test.o -lssl -lcrypto gcc -shared test.o -o libhttps.so gcc -fPIC -shared -o libhttps.so https.c -lssl -lcrypto */ // gcc test.c -lssl -lcrypto

    api:https://wenku.baidu.com/view/e8ae8f5f80eb6294dc886c4c.html#

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <resolv.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <openssl/ssl.h> #include <openssl/err.h> #define MAXBUF 1024 int main(int argc, char **argv) { int sockfd, len; char sendFN[1024]; struct sockaddr_in dest; char buffer[MAXBUF + 1]; SSL_CTX *ctx; SSL *ssl; char host_file[] = ""; char host_addr[] = "www.jd.com"; char ip[] = "113.113.72.3"; //ping int port = 443; /* 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); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket Create Fail!"); exit(errno); } /* 建立 TCP 连接 */ bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(port); if (inet_aton(ip, (struct in_addr *) &dest.sin_addr.s_addr) == 0) { perror("Socket Init Fail!"); exit(errno); } printf("Socket Created\n"); if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { perror("Socket Connect Fail!"); exit(errno); } printf("Socket Connected\n"); /* 绑定 Socket 与 SSL */ ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); /* 建立 SSL 连接 */ if (SSL_connect(ssl) == -1) ERR_print_errors_fp(stderr); else printf("SSL Connected with %s encryption\n", SSL_get_cipher(ssl)); sprintf(sendFN, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Close\r\n\r\n", host_file, host_addr); /* SSL 发数据 */ len = SSL_write(ssl, sendFN, strlen(sendFN)); if (len < 0) printf("SSL Send failure! errno = %d, err_msg = %s\n", errno, strerror(errno)); printf("SSL Send Done !\n\n"); bzero(buffer, MAXBUF + 1); int nbytes; /* SSL 收数据 */ FILE *fp = fopen("jd.html","a"); /* while ((nbytes = SSL_read(ssl, buffer, 1)) == 1) { // 打印收到的数据 //printf("%s", buffer); printf("%d\n",nbytes); fprintf(fp,buffer,strlen(buffer)); }*/ while ((nbytes = SSL_read(ssl, buffer, MAXBUF)) > 0) { /* 打印收到的数据 */ //printf("%s", buffer); //printf("%d\n",nbytes); fprintf(fp,buffer,nbytes); } fclose(fp); printf("\n\nSSL Read Done !\n"); /* 关闭连接 */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); return 0; }

    gdut17@ubuntu:~/skynet_test/cpp$ gcc https.c -o https -lssl -lcrypto gdut17@ubuntu:~/skynet_test/cpp$ ./https Socket Created Socket Connected SSL Connected with TLS_AES_256_GCM_SHA384 encryption SSL Send Done !

    SSL Read Done !

    案例2 实现爬去图片

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <resolv.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <openssl/ssl.h> #include <openssl/err.h> #define MAXBUF 1024 /* https://img30.360buyimg.com/sku/jfs/t1/115858/11/11208/194109/5efc3afcEde49a75f/6ee4dafa374cf473.jpg */ int main(int argc, char **argv) { int sockfd, len; char sendFN[1024]; struct sockaddr_in dest; char buffer[MAXBUF + 1]; SSL_CTX *ctx; SSL *ssl; char host_file[] = "sku/jfs/t1/115858/11/11208/194109/5efc3afcEde49a75f/6ee4dafa374cf473.jpg"; char host_addr[] = "img30.360buyimg.com"; char ip[] = "113.113.72.3"; //ping int port = 443; /* 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); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket Create Fail!"); exit(errno); } /* 建立 TCP 连接 */ bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(port); if (inet_aton(ip, (struct in_addr *) &dest.sin_addr.s_addr) == 0) { perror("Socket Init Fail!"); exit(errno); } printf("Socket Created\n"); if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { perror("Socket Connect Fail!"); exit(errno); } printf("Socket Connected\n"); /* 绑定 Socket 与 SSL */ ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); /* 建立 SSL 连接 */ if (SSL_connect(ssl) == -1) ERR_print_errors_fp(stderr); else printf("SSL Connected with %s encryption\n", SSL_get_cipher(ssl)); sprintf(sendFN, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Close\r\n\r\n", host_file, host_addr); printf("head:\n%s\n",sendFN); /* SSL 发数据 */ len = SSL_write(ssl, sendFN, strlen(sendFN)); if (len < 0) printf("SSL Send failure! errno = %d, err_msg = %s\n", errno, strerror(errno)); printf("SSL Send Done !\n\n"); bzero(buffer, MAXBUF + 1); int nbytes; /* SSL 收数据 */ /* while ((nbytes = SSL_read(ssl, buffer, 1)) == 1) { // 打印收到的数据 //printf("%s", buffer); printf("%d\n",nbytes); fprintf(fp,buffer,strlen(buffer)); }*/ //read header char ch; while ((nbytes = SSL_read(ssl, &ch, 1)) == 1) { printf("%c",ch); if (ch=='\r') { nbytes = SSL_read(ssl, &ch, 1); printf("%c",ch); if (nbytes>0 && ch=='\n') { nbytes = SSL_read(ssl, &ch, 1); printf("%c",ch); if (nbytes>0 && ch=='\r') { nbytes = SSL_read(ssl, &ch, 1); printf("%c",ch); if (nbytes>0 && ch=='\n') { break; } } } } } FILE *fp = fopen("jd.jpg","wb"); //read body int body_len = 0; while ((nbytes = SSL_read(ssl, buffer, MAXBUF)) > 0) { body_len += nbytes; fwrite(buffer,nbytes,1,fp); } fclose(fp); printf("body_len %d\n",body_len); printf("\n\nSSL Read Done !\n"); /* 关闭连接 */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); return 0; } gdut17@ubuntu:~/skynet_test/cpp$ gcc https.c -o https -lssl -lcrypto gdut17@ubuntu:~/skynet_test/cpp$ ./https Socket Created Socket Connected SSL Connected with TLS_AES_256_GCM_SHA384 encryption head: GET /sku/jfs/t1/115858/11/11208/194109/5efc3afcEde49a75f/6ee4dafa374cf473.jpg HTTP/1.1 Host: img30.360buyimg.com Connection: Close SSL Send Done ! HTTP/1.1 200 OK Server: nginx Date: Thu, 08 Oct 2020 07:36:42 GMT Content-Type: image/jpeg Content-Length: 194109 Connection: close Age: 3698155 Cache-Control: max-age=315360000 Expires: Fri, 19 Aug 2050 12:20:47 GMT Last-Modified: Wed, 01 Jul 2020 07:27:56 GMT Via: http/1.1 ORI-BJ-CT-YF-FCS-30 (jcs [cHs f ]), http/1.1 ORI-CLOUD-HEN2-MIX-12 (jcs [cMsSfW]), http/1.1 GD-CT-1-MIX-20 (jcs [cRs f ]) Access-Control-Allow-Origin: * Timing-Allow-Origin: * X-Trace: 200-1598444447230-0-0-4-47-47;200-1601734209907-0-0-0-28-28;200;200-1601734209900-0-0-0-47-47;200-1602142602295-0-0-0-0-0 body_len 194109 SSL Read Done !
    Processed: 0.012, SQL: 8