热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

openssl实现https网站

下面是一个用openssl实现获取https网页内容的demo,整个流程比较简单,主要封装的API如下staticinthttps_init(http

下面是一个用openssl  实现获取https 网页内容的demo,整个流程比较简单,主要封装的API如下

static int https_init(https_context_t *context,const char* url);
static int https_uninit(https_context_t *context);
static int https_read(https_context_t *context,void* buff,int len);
static int https_write(https_context_t *context,const void* buff,int len);
static int https_get_status_code(https_context_t *context);
static int https_read_content(https_context_t *context,char *resp_contet,int max_len);

通信流程:

1、初始化,解析url资源,创建socket 连接,绑定ssl

2、发送http 请求

3、获取请求返回的状态码

4、获取请求返回的数据

5、销毁动态申请的内存资源

我就把整个代码贴在下面


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include #define HTTP_REQ_LENGTH 512
#define HTTP_RESP_LENGTH 20480typedef struct
{int sock_fd;SSL_CTX *ssl_ct;SSL *ssl;//url 解析出来的信息char *host;char *path;int port;
} https_context_t;static int https_init(https_context_t *context,const char* url);
static int https_uninit(https_context_t *context);
static int https_read(https_context_t *context,void* buff,int len);
static int https_write(https_context_t *context,const void* buff,int len);
static int https_get_status_code(https_context_t *context);
static int https_read_content(https_context_t *context,char *resp_contet,int max_len);// http 请求头信息
static char https_header[] ="GET %s HTTP/1.1\r\n""Host: %s:%d\r\n""Connection: Close\r\n""Accept: */*\r\n""\r\n";static char http_req_content[HTTP_REQ_LENGTH] = {0};
static char https_resp_content[HTTP_RESP_LENGTH+1] = {0};static int create_request_socket(const char* host,const int port)
{int sockfd;struct hostent *server;struct sockaddr_in serv_addr;sockfd &#61; socket(AF_INET, SOCK_STREAM, 0);if (sockfd <0){printf("[http_demo] create_request_socket create socket fail.\n");return -1;}/* lookup the ip address */server &#61; gethostbyname(host);if(server &#61;&#61; NULL){printf("[http_demo] create_request_socket gethostbyname fail.\n");close(sockfd);return -1;}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family &#61; AF_INET;serv_addr.sin_port &#61; htons(port);memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0){printf("[http_demo] create_request_socket connect fail.\n");close(sockfd);return -1;}return sockfd;
}/*** &#64;brief https_parser_url 解析出https 中的域名、端口和路径* &#64;param url 需要解析的url* &#64;param host 解析出来的域名或者ip* &#64;param port 端口&#xff0c;没有时默认返回443* &#64;param path 路径&#xff0c;指的是域名后面的位置* &#64;return*/
static int https_parser_url(const char* url,char **host,int *port,char **path)
{if(url &#61;&#61; NULL || strlen(url) <9 || host &#61;&#61; NULL || path &#61;&#61; NULL){printf("[https_demo] url or host or path is null.\n");return -1;}//判断是不是 https://int i &#61; 0;char https_prefix[] &#61; "https://";for(i&#61;0;i<8;i&#43;&#43;){if(url[i] !&#61; https_prefix[i]){printf("[https_demo] illegal url &#61; %s.\n",url);return -1;}}const char *temp &#61; url&#43;i;while(*temp !&#61; &#39;/&#39;) //next /{if(*temp &#61;&#61; &#39;\0&#39;) //{printf("[https_demo] illegal url &#61; %s.\n",url);return -1;}temp&#43;&#43;;}const char *host_port &#61; url&#43;i;while(*host_port !&#61; &#39;:&#39; && *host_port !&#61; &#39;/&#39;) //找到 :或者 / 结束{host_port &#43;&#43;;}int host_len &#61; host_port-url-i; //减掉https://int path_len &#61; strlen(temp);char *host_temp &#61; (char *)malloc(host_len &#43; 1); //多一个字符串结束标识 \0if(host_temp &#61;&#61; NULL){printf("[https_demo] malloc host fail.\n");return -1;}if(*host_port&#43;&#43; &#61;&#61; &#39;:&#39;) //url 中有端口{*port &#61; 0;while(*host_port !&#61;&#39;/&#39; && *host_port !&#61;&#39;\0&#39;) //十进制字符串转成数字{*port *&#61; 10;*port &#43;&#61; (*host_port - &#39;0&#39;);host_port &#43;&#43;;}}else{*port &#61; 443;}char *path_temp &#61; (char *)malloc(path_len &#43; 1); //多一个字符串结束标识 \0if(path_temp &#61;&#61; NULL){printf("[https_demo] malloc path fail.\n");free(host_temp);return -1;}memcpy(host_temp,url&#43;i,host_len);memcpy(path_temp,temp,path_len);host_temp[host_len] &#61; &#39;\0&#39;;path_temp[path_len] &#61; &#39;\0&#39;;*host &#61; host_temp;*path &#61; path_temp;return 0;
}static int https_init(https_context_t *context,const char* url)
{if(context &#61;&#61; NULL){printf("[https_demo] init https_context_t is null.\n");return -1;}if(https_parser_url(url,&(context->host),&(context->port),&(context->path))){printf("[https_demo] https_parser_url fail.\n");return -1;}context->sock_fd &#61; create_request_socket(context->host,context->port);if(context->sock_fd <0){printf("[https_demo] create_request_socket fail.\n");goto https_init_fail;}context->ssl_ct &#61; SSL_CTX_new(SSLv23_method());if(context->ssl_ct &#61;&#61; NULL){printf("[https_demo] SSL_CTX_new fail.\n");goto https_init_fail;}context->ssl &#61; SSL_new(context->ssl_ct);if(context->ssl &#61;&#61; NULL){printf("[https_demo] SSL_new fail.\n");goto https_init_fail;}if(SSL_set_fd(context->ssl,context->sock_fd)<0){printf("[https_demo] SSL_set_fd fail \n");}if(SSL_connect(context->ssl) &#61;&#61; -1){printf("[https_demo] SSL_connect fail.\n");goto https_init_fail;}return 0;
https_init_fail:https_uninit(context);return -1;
}static int https_read(https_context_t *context,void* buff,int len)
{if(context &#61;&#61; NULL || context->ssl &#61;&#61; NULL){printf("[https_demo] read https_context_t or ssl is null.\n");return -1;}return SSL_read(context->ssl,buff,len);
}static int https_write(https_context_t *context,const void* buff,int len)
{if(context &#61;&#61; NULL || context->ssl &#61;&#61; NULL){printf("[https_demo] write https_context_t or ssl is null.\n");return -1;}return SSL_write(context->ssl,buff,len);
}static int https_get_status_code(https_context_t *context)
{if(context &#61;&#61; NULL || context->ssl &#61;&#61; NULL){printf("[https_demo] get status https_context_t or ssl is null.\n");return -1;}int ret;int flag &#61;0;int recv_len &#61; 0;char res_header[1024] &#61; {0};while(recv_len<1023){ret &#61; SSL_read(context->ssl, res_header&#43;recv_len, 1);if(ret<1) // recv fail{break;}//找到响应头的头部信息, 两个"\r\n"为分割点if((res_header[recv_len]&#61;&#61;&#39;\r&#39;&&(flag&#61;&#61;0||flag&#61;&#61;2))||(res_header[recv_len]&#61;&#61;&#39;\n&#39;&&(flag&#61;&#61;1||flag&#61;&#61;3))){flag&#43;&#43;;}else{flag &#61; 0;}recv_len&#43;&#61;ret;if(flag&#61;&#61;4){break;}}//printf("[http_demo] recv_len&#61;%d res_header &#61; %s.\n",recv_len,res_header);/*获取响应头的信息*/int status_code &#61; -1;char *pos &#61; strstr(res_header, "HTTP/");if(pos){sscanf(pos, "%*s %d", &status_code);//返回状态码}return status_code;
}static int https_read_content(https_context_t *context,char *resp_contet,int max_len)
{if(context &#61;&#61; NULL || context->ssl &#61;&#61; NULL){printf("[https_demo] read content https_context_t or ssl is null.\n");return -1;}int ret ;int recv_size &#61; 0;while(recv_size ssl,resp_contet &#43; recv_size,max_len-recv_size);if(ret <1){break;}recv_size &#43;&#61; ret;}return recv_size;
}static int https_uninit(https_context_t *context)
{if(context &#61;&#61; NULL){printf("[https_demo] uninit https_context_t is null.\n");return -1;}if(context->host !&#61; NULL){free(context->host);context->host &#61; NULL;}if(context->path !&#61; NULL){free(context->path);context->path &#61; NULL;}if(context->ssl !&#61; NULL){SSL_shutdown(context->ssl);//SSl_free(context->ssl);context->ssl &#61; NULL;}if(context->ssl_ct !&#61; NULL){SSL_CTX_free(context->ssl_ct);context->ssl_ct &#61; NULL;}if(context->sock_fd > 0){close(context->sock_fd);context->sock_fd &#61; -1;}return 0;
}int main()
{https_context_t https_ct &#61; {0};int ret &#61; SSL_library_init();printf("[https_demo] SSL_library_init ret &#61; %d.\n",ret);https_init(&https_ct,"https://www.baidu.com/");ret &#61; snprintf(http_req_content,HTTP_REQ_LENGTH,https_header,https_ct.path,https_ct.host,https_ct.port);ret &#61; https_write(&https_ct,http_req_content,ret);printf("[https_demo] https_write ret &#61; %d.\n",ret);if(https_get_status_code(&https_ct) &#61;&#61; 200){ret &#61; https_read_content(&https_ct,https_resp_content,HTTP_RESP_LENGTH);if(ret > 0){https_resp_content[ret] &#61; &#39;\0&#39;; //字符串结束标识printf("[https_demo] https_write https_resp_content &#61; \n %s.\n",https_resp_content);}}https_uninit(&https_ct);return 0;
}

 


推荐阅读
  • Java中处理NullPointerException:getStackTrace()方法详解与实例代码 ... [详细]
  • 本文深入探讨了CGLIB BeanCopier在Bean对象复制中的应用及其优化技巧。相较于Spring的BeanUtils和Apache的BeanUtils,CGLIB BeanCopier在性能上具有显著优势。通过详细分析其内部机制和使用场景,本文提供了多种优化方法,帮助开发者在实际项目中更高效地利用这一工具。此外,文章还讨论了CGLIB BeanCopier在复杂对象结构和大规模数据处理中的表现,为读者提供了实用的参考和建议。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • 本文探讨了利用Java实现WebSocket实时消息推送技术的方法。与传统的轮询、长连接或短连接等方案相比,WebSocket提供了一种更为高效和低延迟的双向通信机制。通过建立持久连接,服务器能够主动向客户端推送数据,从而实现真正的实时消息传递。此外,本文还介绍了WebSocket在实际应用中的优势和应用场景,并提供了详细的实现步骤和技术细节。 ... [详细]
  • Java SE 文件操作类详解与应用
    ### Java SE 文件操作类详解与应用#### 1. File 类##### 1.1 File 类概述File 类是 Java SE 中用于表示文件和目录路径名的对象。它提供了丰富的方法来操作文件和目录,包括创建、删除、重命名文件,以及获取文件属性和信息。通过 File 类,开发者可以轻松地进行文件系统操作,如检查文件是否存在、读取文件内容、列出目录下的文件等。此外,File 类还支持跨平台操作,确保在不同操作系统中的一致性。 ... [详细]
  • 在处理大图片时,PHP 常常会遇到内存溢出的问题。为了避免这种情况,建议避免使用 `setImageBitmap`、`setImageResource` 或 `BitmapFactory.decodeResource` 等方法直接加载大图。这些函数在处理大图片时会消耗大量内存,导致应用崩溃。推荐采用分块处理、图像压缩和缓存机制等策略,以优化内存使用并提高处理效率。此外,可以考虑使用第三方库如 ImageMagick 或 GD 库来处理大图片,这些库提供了更高效的内存管理和图像处理功能。 ... [详细]
  • 如何使用和示例代码解析 org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom.getPropertyChain() 方法 ... [详细]
  • 开发笔记:深入解析Android自定义控件——Button的72种变形技巧
    开发笔记:深入解析Android自定义控件——Button的72种变形技巧 ... [详细]
  • 在Java编程中,若需实现两个整数(例如2和3)相除并保留两位小数的结果,可以通过精确计算方法来达到预期效果。具体而言,可以利用BigDecimal类进行高精度运算,确保2除以3的结果准确显示为0.66。此外,还可以通过格式化输出来控制小数位数,确保最终结果符合要求。 ... [详细]
  • 深入解析 Android TextView 中 getImeActionLabel() 方法的使用与代码示例 ... [详细]
  • 如果程序使用Go语言编写并涉及单向或双向TLS认证,可能会遭受CPU拒绝服务攻击(DoS)。本文深入分析了CVE-2018-16875漏洞,探讨其成因、影响及防范措施,为开发者提供全面的安全指导。 ... [详细]
  • Eclipse JFace Text框架中IDocument接口的getNumberOfLines方法详解与编程实例 ... [详细]
  • 大家好,我是梅巴哥er。本文将深入探讨Redux框架中的第三个实战案例,具体实现每两秒自动点击按钮以触发颜色变化的功能。该案例中,一个关键点在于是否需要使用异步操作来处理定时任务,我们将详细分析其必要性和实现方式。通过这一实例,读者可以更好地理解Redux在实际项目中的应用及其异步处理机制。 ... [详细]
  • 题目:图像处理(HDU1828,计算周长并集,利用线段树与离散化技术进行扫描) ... [详细]
  • 在探讨C语言编程文本编辑器的最佳选择与专业推荐时,本文将引导读者构建一个基础的文本编辑器程序。该程序不仅能够打开并显示文本文件的内容及其路径,还集成了菜单和工具栏功能,为用户提供更加便捷的操作体验。通过本案例的学习,读者可以深入了解文本编辑器的核心实现机制。 ... [详细]
author-avatar
111222
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有