`
zsxxsz
  • 浏览: 452046 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用 acl 较为底层的 HTTP 协议库写 HTTP 下载客户端举例

阅读更多

  在" 使用 acl 库开发一个 HTTP 下载客户端" 文章中介绍利用ACL库中的 HTTP 高级API函数编写HTTP下载客户端的简单的例子,本文介绍一下如何使用稍微底层的API来编写同样功能的例子。在这个例子中,可以看到那些高级API是如何封装底层API的。

  请先看一个例子如下:

#include "lib_acl.h"
#include "lib_protocol.h"

static void get_url(const char *method, const char *url,
	const char *proxy, const char *dump)
{
	/* 创建 HTTP 请求头 */
	HTTP_HDR_REQ *hdr_req = http_hdr_req_create(url, method, "HTTP/1.1");
	ACL_VSTREAM *stream;  /* 网络连接流 */
	ACL_VSTRING *buf = acl_vstring_alloc(256);  /* 分配内存缓冲区 */
	HTTP_HDR_RES *hdr_res;  /* HTTP 响应头 */
	HTTP_RES *res;  /* HTTP响应体 */
	ACL_FILE *fp = NULL;  /* 转储文件句柄 */
	const char *ptr;
	int   ret;

	/* 输出 HTTP 请求头内容 */

	http_hdr_print(&hdr_req->hdr, "---request hdr---");

	/* 如果设定代理服务器,则连接代理服务器地址,
	 * 否则使用 HTTP 请求头里指定的地址
	 */

	if (*proxy)
		acl_vstring_strcpy(buf, proxy);
	else
		acl_vstring_strcpy(buf, http_hdr_req_host(hdr_req));

	/* 获得远程 HTTP 服务器的连接地址 */

	ptr = acl_vstring_memchr(buf, ':');
	if (ptr == NULL)
		acl_vstring_strcat(buf, ":80");
	else {
		int   port;
		ptr++;
		port = atoi(ptr);
		if (port <= 0 || port >= 65535) {
			printf("http server's addr(%s) invalid\n", acl_vstring_str(buf));
			acl_vstring_free(buf);
			http_hdr_req_free(hdr_req);
			return;
		}
	}

	/* 连接远程 http 服务器 */

	stream = acl_vstream_connect(acl_vstring_str(buf) /* 服务器地址 */,
			ACL_BLOCKING /* 采用阻塞方式 */,
			10 /* 连接超时时间为 10 秒 */,
			10 /* 网络 IO 操作超时时间为 10 秒 */,
			4096 /* stream 流缓冲区大小为 4096 字节 */);
	if (stream == NULL) {
		/* 连接服务器失败 */

		printf("connect addr(%s) error(%s)\n",
			acl_vstring_str(buf), acl_last_serror());
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 构建 HTTP 请求头数据 */

	http_hdr_build_request(hdr_req, buf);

	/* 向 HTTP 服务器发送请求 */

	ret = acl_vstream_writen(stream, acl_vstring_str(buf), ACL_VSTRING_LEN(buf));
	if (ret == ACL_VSTREAM_EOF) {
		printf("write to server error(%s)\n", acl_last_serror());
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 创建一个 HTTP 响应头对象 */

	hdr_res = http_hdr_res_new();

	/* 读取 HTTP 服务器响应头*/

	ret = http_hdr_res_get_sync(hdr_res, stream, 10 /* IO 超时时间为 10 秒 */);
	if (ret < 0) {
		printf("get http reply header error(%s)\n", acl_last_serror());
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 分析HTTP服务器响应头 */

	if (http_hdr_res_parse(hdr_res) < 0) {
		printf("parse http reply header error\n");
		http_hdr_print(&hdr_res->hdr, "--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 如果需要转储至磁盘则需要先打开文件 */

	if (dump != NULL) {
		fp = acl_fopen(dump, "w+");
		if (fp == NULL)
			printf("open file(%s) error(%s)\n",
				dump, acl_last_serror());
	}

	/* 如果 HTTP 响应没有数据体则仅输出 HTTP 响应头即可 */

	if (hdr_res->hdr.content_length == 0
		|| (hdr_res->hdr.content_length == -1
			&& !hdr_res->hdr.chunked
			&& hdr_res->reply_status > 300
			&& hdr_res->reply_status < 400))
	{
		if (fp)
			http_hdr_fprint(ACL_FSTREAM(fp), &hdr_res->hdr,
				"--- reply http header ---");
		else
			http_hdr_fprint(ACL_VSTREAM_OUT, &hdr_res->hdr,
				"--- reply http header ---");
		http_hdr_res_free(hdr_res);
		acl_vstream_close(stream);
		acl_vstring_free(buf);
		http_hdr_req_free(hdr_req);
		return;
	}

	/* 输出 HTTP 响应头 */

	http_hdr_print(&hdr_res->hdr, "--- reply http header ---");

	/* 创建 HTTP 响应体对象 */

	res = http_res_new(hdr_res);

	/* 如果有数据体则开始读取 HTTP 响应数据体部分 */

	while (1) {
		http_off_t  n;
		char  buf2[4096];
		
		/* 以同步方式读取HTTP响应数据 */

		n = http_res_body_get_sync(res, stream, buf2, sizeof(buf2) - 1);
		if (n <= 0)
			break;

		if (fp) {
			/* 转储至文件中 */

			if (acl_fwrite(buf2, (size_t) n, 1, fp) == (size_t) EOF) {
				printf("write to dump file(%s) error(%s)\n",
					dump, acl_last_serror());
				break;
			}
		} else {
			buf2[n] = 0;
			printf("%s", buf2);
		}
	}

	if (fp)
		acl_fclose(fp);  /* 关闭转储文件句柄 */
	http_res_free(res);  /* 释放 HTTP 响应对象, hdr_res 会在此函数内部自动被释放 */
	acl_vstream_close(stream);  /* 关闭网络流 */
	acl_vstring_free(buf);  /* 释放内存区 */
	http_hdr_req_free(hdr_req);  /* 释放 HTTP 请求头对象 */
}

static void usage(const char *procname)
{
	printf("usage: %s -h[help] -t method -r url -f dump_file -X proxy_addr\n"
		"example: %s -t GET -r http://www.sina.com.cn/ -f url_dump.txt\n",
		procname, procname);
}

int main(int argc, char *argv[])
{
	int   ch;
	char  url[256], dump[256], proxy[256], method[32];

	acl_init();  /* 初始化 acl 库 */

	ACL_SAFE_STRNCPY(method, "GET", sizeof(method));
	url[0] = 0;
	dump[0] = 0;
	proxy[0] = 0;
	while ((ch = getopt(argc, argv, "hr:t:f:X:")) > 0) {
		switch (ch) {
		case 'h':
			usage(argv[0]);
			return (0);
		case 'r':
			ACL_SAFE_STRNCPY(url, optarg, sizeof(url));
			break;
		case 't':
			ACL_SAFE_STRNCPY(method, optarg, sizeof(method));
			break;
		case 'f':
			ACL_SAFE_STRNCPY(dump, optarg, sizeof(dump));
			break;
		case 'X':
			ACL_SAFE_STRNCPY(proxy, optarg, sizeof(proxy));
			break;
		default:
			break;
		}
	}

	if (url[0] == 0) {
		usage(argv[0]);
		return (0);
	}

	get_url(method, url, proxy, dump);
	return (0);
}

   可以明显地看出,该例子的实现代码量要比 使用 acl 库开发一个 HTTP 下载客户端 麻烦许多,但它却比较清晰地展示了 HTTP 协议的请求与响应过程。该例子可以在 acl_project/samples/http/get_url1/ 目录下找到。

      acl 库下载: http://acl.sourceforge.net/

      个人微博:http://weibo.com/zsxxsz

 

0
0
分享到:
评论

相关推荐

    acl C++跨平台库.rar

    lib_acl_cpp 库的 db 模块依赖于 mysql 客户端库、sqlite 库,stream 流模块依赖于 polarssl 库(该库源码附在 acl/resource 目录下),另外,在 UNIX/LINUX 平台下还需要压缩库 --- libz 库(一般 LINUX 会自带该...

    H3C交换机 典型配置举例-6W100-ACL典型配置举例

    "H3C交换机典型配置举例-6W100-ACL典型配置举例" 本文将详细介绍H3C交换机中的ACL(Access Control List,访问控制列表)典型配置举例,包括允许指定的主机访问网络和拒绝指定的主机访问网络两种配置举例。 首先,...

    acl.2.1.2.8.src.2012.7.2.zip_ACL_ACL_http_http json_协议

    ACL库的JSON解析器使得处理JSON数据更加高效,便于在服务器与客户端之间进行数据交互。 9. **源代码版本**:文件名中的“src”表明这是一个源代码包,意味着用户可以查看和编译原始代码,根据需求进行定制和优化。 ...

    基于acl库封装c\c++ 的redis-client客户端源码

    基于acl库封装的redis client vs2010工程; 运行时解压到: redis-acl\lib_acl_cpp\samples\redis路径下,把lib_acl_vc2010d.lib、lib_...依赖的库 需要下载开源 源码编出来 : svn://svn.code.sf.net/p/acl/code/trunk

    acl库 (advanced c library)

    ACL库,全称为Advanced C Library,是一个为C程序员设计的跨平台库,旨在提供一系列高效且易用的数据处理算法,以及强大的服务器框架。这个库特别适合于开发需要高性能、高并发性和良好扩展性的网络应用程序。在本文...

    acl库,编译好的库文件

    在本例中,提供的“acl库,编译好的库文件”是一个已经预编译的版本,这意味着它可以直接被下载并使用,无需用户自行编译源代码。这对于开发者来说是一个极大的便利,因为编译过程可能涉及到许多依赖项和配置步骤,...

    实验:使用基本ACL限制公司网络访问.docx

    本实验"使用基本ACL限制公司网络访问"旨在让学生深入理解并掌握如何通过访问控制列表(ACL)来实现这一目标。实验主要涉及了eNSP(Enterprise Network Simulation Platform,企业网络模拟平台)、ACL、VLAN以及三层...

    使用基本ACL限制公司网络访问.rar

    3、应用场景:使用基本ACL限制公司网络访问 4、特点:Word文档提供了实验的详细过程,包括每一步骤的操作命令和截图,并给出了实验的topo文件(包括配置信息) 5、适用人群:网络系统的建设与运维 6、使用说明:重点...

    ACL访问控制协议PPT

    **ACL访问控制协议详解** **一、什么是ACL** ACL(Access Control List,访问控制列表)是一种网络设备(如路由器、交换机)上用于控制网络流量的机制。它是一系列有序的规则,用来允许或拒绝特定的数据包通过网络...

    前端开源库-acl

    前端开源库-acl基于Redis的访问控制列表模块acl,支持快速中间件

    acl-3.0.19

    lib_acl(纯C开发的基础库,主要包含网络通信及服务器编程框架以及其它丰富的功能)、lib_protocol(包含 HTTP/PING/SMTP 通信协议的C语言实现)、lib_acl_cpp(基于 lib_acl 及 lib_protocol 两个C库,提供了更为强大的...

    掌握ACL的配置方法

    - 添加规则:在ACL中使用`permit`或`deny`命令定义允许或拒绝的规则,指定源IP地址和协议。 - 应用ACL:在接口配置模式下,使用`ip access-group`命令将ACL应用到接口的入站或出站方向。 2. **扩展ACL**:除了源...

    Redis 6.0核心创新:多线程、客户端缓存和ACL详解

    Redis 6.0的核心创新在于其引入了多线程、客户端缓存以及访问控制列表(ACL)这三大特性,显著提升了系统性能和安全性。 首先,让我们深入探讨Redis 6.0的多线程特性。在之前的版本中,Redis采用的是单线程模型执行...

    acl 的使用方法

    ACL 使用方法详解 ACL(Access Control List,访问控制列表)是一种报文过滤器,能够根据报文的特征来过滤报文,从而提高网络环境的安全性和网络传输的可靠性。ACL 由一系列规则组成,这些规则可以是报文的源地址、...

    acl 框架库-其他

    1、常见网络应用库:SMTP 客户端库/PING 库/memcache 客户端库/handlersocket 客户端库/beanstalk 客户端库 2、HTTP 网络库:HTTP 客户端/服务端库,C++版 HttpServlet 类,HTTP COOKIE/HTTP SESSION 等 3、邮件解析...

    acl-master.zip_ACL库_c++ acl_git acl-master

    acl_cpp 是基于 acl 库的 C++ 库,包括 MIIME 解析、Handlersocket 客户端库、数据库连接池(支持mysql/sqlite)、WEB 编程、数据库编程、阻塞/非阻塞数据流等内容。

    ACL奇数偶数匹配.doc

    根据这个规律,我们可以写出两个 ACL 来分别匹配奇数和偶数的网络号。 在实验中,我们使用了 access-list 1 来匹配偶数的网络号,使用了 access-list 2 来匹配奇数的网络号。我们还使用了 route-map 来将这两个 ACL...

    01-acl.rar

    1. **库函数**:在C语言编程中,可以使用`libacl`库来操作ACL,它提供了如`acl_init`,`acl_set_file`等函数接口。 2. **程序设计**:编写系统级程序时,理解并正确处理ACL对于确保文件和资源的安全性至关重要。 3. ...

    使用扩展ACL限制公司网络访问.rar

    3、应用场景:使用扩展ACL限制公司网络访问 4、特点:Word文档提供了实验的详细过程,包括每一步骤的操作命令和截图,并给出了实验的topo文件(包括配置信息) 5、适用人群:网络系统的建设与运维 6、使用说明:重点...

    ACL从入门到精通

    通过使用ACL,网络管理员可以有效地控制网络访问,提高安全性,防止非法入侵,实现服务质量(QoS)策略,以及对网络流量进行精细化管理。 **2. ACL的分类** 在Cisco设备中,ACL通常分为两种类型:标准ACL和扩展ACL...

Global site tag (gtag.js) - Google Analytics