在 acl 的协议库(lib_protocol) 中有专门针对 HTTP 协议和 ICMP 协议的,本文主要介绍如何使用 lib_protocol 协议库来开发一个简单的 http 客户端。下面首先介绍一下几个本文用到的函数接口。
/** * 创建一个 HTTP_UTIL 请求对象 * @param url {const char*} 完整的请求 url * @param method {const char*} 请求方法,有效的请求方法有:GET, POST, HEAD, CONNECT * @return {HTTP_UTIL*} */ HTTP_API HTTP_UTIL *http_util_req_new(const char *url, const char *method); /** * 设置 HTTP 代理服务器地址 * @param http_util {HTTP_UTIL*} * @param proxy {const char*} 代理服务器地址,有效格式为: IP:PORT, DOMAIN:PORT, * 如: 192.168.0.1:80, 192.168.0.2:8088, www.g.cn:80 */ HTTP_API void http_util_set_req_proxy(HTTP_UTIL *http_util, const char *proxy); /** * 设置 HTTP 响应体的转储文件,设置后 HTTP 响应体数据便会转储于该文件 * @param http_util {HTTP_UTIL*} * @param filename {const char*} 转储文件名 * @return {int} 如果返回值 < 0 则表示无法打开该文件, 否则表示打开文件成功 */ HTTP_API int http_util_set_dump_file(HTTP_UTIL *http_util, const char *filename); /** * 打开远程 HTTP 服务器或代理服务器连接,同时构建 HTTP 请求头数据并且将该数据 * 发给新建立的网络连接 * @param http_util {HTTP_UTIL*} * @return {int} 0: 成功; -1: 无法打开连接或发送请求头数据失败 */ HTTP_API int http_util_req_open(HTTP_UTIL *http_util); /** * 发送完请求数据后调用此函数从 HTTP 服务器读取完整的 HTTP 响应头 * @param http_util {HTTP_UTIL*} * @return {int} 0: 成功; -1: 失败 */ HTTP_API int http_util_get_res_hdr(HTTP_UTIL *http_util); /** * 读完 HTTP 响应头后调用此函数从 HTTP 服务器读取 HTTP 数据体数据,需要连续调用 * 此函数,直至返回值 <= 0, 如果之前设置了转储文件或转储则在读取数据过程中同时会 * 拷贝一份数据给转储文件或转储流 * @param http_util {HTTP_UTIL*} * @param buf {char *} 存储 HTTP 响应体的缓冲区 * @param size {size_t} buf 的空间大小 * @return {int} <= 0: 表示读结束; > 0: 表示本次读到的数据长度 */ HTTP_API int http_util_get_res_body(HTTP_UTIL *http_util, char *buf, size_t size);
以上仅是 lib_http_util.h 函数接口中的一部分,下面就写一个简单的例子:
#include "lib_acl.h" #include "lib_protocol.h" static void get_url(const char *method, const char *url, const char *proxy, const char *dump, int out) { /* 创建 HTTP_UTIL 请求对象 */ HTTP_UTIL *http = http_util_req_new(url, method); int ret; /* 如果设定代理服务器,则连接代理服务器地址, * 否则使用 HTTP 请求头里指定的地址 */ if (proxy && *proxy) http_util_set_req_proxy(http, proxy); /* 设置转储文件 */ if (dump && *dump) http_util_set_dump_file(http, dump); /* 输出 HTTP 请求头内容 */ http_hdr_print(&http->hdr_req->hdr, "---request hdr---"); /* 连接远程 http 服务器 */ if (http_util_req_open(http) < 0) { printf("open connection(%s) error\n", http->server_addr); http_util_free(http); return; } /* 读取 HTTP 服务器响应头*/ ret = http_util_get_res_hdr(http); if (ret < 0) { printf("get reply http header error\n"); http_util_free(http); return; } /* 输出 HTTP 响应头 */ http_hdr_print(&http->hdr_res->hdr, "--- reply http header ---"); /* 如果有数据体则开始读取 HTTP 响应数据体部分 */ while (1) { char buf[4096]; ret = http_util_get_res_body(http, buf, sizeof(buf) - 1); if (ret <= 0) break; buf[ret] = 0; if (out) printf("%s", buf); } http_util_free(http); } static void usage(const char *procname) { printf("usage: %s -h[help] -t method -r url -f dump_file -o[output] -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, out = 0; 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, "hor:t:f:X:")) > 0) { switch (ch) { case 'h': usage(argv[0]); return (0); case 'o': out = 1; break; 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, out); return (0); }
编译成功后,运行 ./url_get -h 会给出如下提示:
usage: ./url_get -h[help] -t method -r url -f dump_file -o[output] -X proxy_addr
example: ./url_get -t GET -r http://www.sina.com.cn/ -f url_dump.txt
输入: ./url_get -t GET -r http://www.sina.com -o, 该命令是获取 www.sina.com 页面并输出至标准输出,得到的结果为:
HTTP/1.0 301 Moved Permanently Date: Tue, 12 Jan 2010 01:54:39 GMT Server: Apache Location: http://www.sina.com.cn/ Cache-Control: max-age=3600 Expires: Tue, 12 Jan 2010 02:54:39 GMT Vary: Accept-Encoding Content-Length: 231 Content-Type: text/html; charset=iso-8859-1 Age: 265 X-Cache: HIT from tj175-135.sina.com.cn Connection: close --------------- end ----------------- <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="http://www.sina.com.cn/">here</a>.</p> </body></html>
如果想把页面转存至文件中,可以输入:./url_get -t GET -r http://www.sina.com -f dump.txt, 这样就会把新浪的首页下载并存储于 dump.txt 文件中。
这个例子非常简单,其实如果查看 http_util.c 源码,会看到这个文件是对 lib_http.h 里一些更为底层 API 的封装。
如果仅是下载一个页面至某个文件中,其实还有更为简单的方法,只需要调用接口:
/** * 将某个 url 的响应体数据转储至某个文件中 * @param url {const char*} 完整请求 url, 如: http://www.g.cn * @param dump {const char*} 转储文件名 * @param {int} 读到的响应体数据长度, >=0: 表示成功, -1: 表示失败 */ HTTP_API int http_util_dump_url(const char *url, const char *dump);
只这一个函数便可以达到与上一个例子相同的效果。
可以从 acl.sourceforge.net 上下载最新的 acl_project 库,查看 samples/http/ 下的三个例子,看一下下载WEB文件的不同方式。
相关推荐
ACL库,全称为Advanced C Library,是一个为C程序员设计的跨平台库,旨在提供一系列高效且易用的数据处理算法,以及强大的服务器...对于想要深入C语言网络编程的开发者来说,ACL库无疑是一个值得学习和使用的优秀库。
ACL库的JSON解析器使得处理JSON数据更加高效,便于在服务器与客户端之间进行数据交互。 9. **源代码版本**:文件名中的“src”表明这是一个源代码包,意味着用户可以查看和编译原始代码,根据需求进行定制和优化。 ...
TortoiseSVN是一个流行的Subversion客户端,它作为一个Windows Shell扩展集成到操作系统中,提供了直观的图形用户界面。这个版本1.4.8是针对Windows 32位系统的,支持Subversion 1.4.6版本。TortoiseSVN允许用户...
acl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、...
acl 框架库是一个 C 库,主要包含:服务器开发框架、同步/异步网络通讯、常用数据结构、进程池/线程池、流式 xml/json 解析器、http/ping 应用协议等内容。 acl 包括以下丰富的常用函数库: 1、常见网络应用库:SMTP...
【CVS服务器+客户端】是版本控制系统CVS(Concurrent Versions System)在Windows平台上的应用,主要用于协同开发和管理代码库。CVS是一种开源的、网络化的版本控制系统,它允许多个开发者同时对同一份代码进行修改...
标题“lua and acl example”揭示了本主题是关于使用Lua脚本语言与Access Control Lists (ACL)相结合的一个示例。Lua是一种轻量级的、解释型的编程语言,常用于游戏开发、配置文件、服务器应用等领域。而ACL则通常...
- 在Linux环境下,常用的C++ MQTT库有Paho MQTT C++库(由IBM维护)和mosquitto库(一个开源MQTT代理及客户端实现)。 - Paho MQTT C++库提供了易于使用的API,支持连接、发布、订阅和断开连接等功能。 - ...
4. **lib_acl_cpp**:这个文件名有些不完整,但根据上下文推测,它可能与C++版本的ACL库有关,可能是另一个部分或更新的版本。 在实际开发中,开发者需要将这些库文件链接到他们的C++项目中,通过`#include`指令...
客户端是Zookeeper与用户交互的主要界面,理解其工作原理和使用方法对于开发和维护分布式应用至关重要。本篇文章将深入探讨Zookeeper客户端的相关知识点。 1. **客户端连接** Zookeeper客户端通过TCP连接到...
ACL项目是一个综合性的软件开发项目,其核心是提供一套通用且跨平台的函数库,旨在简化和优化IT领域的多个关键领域。...通过深入理解和使用ACL库,开发者可以更专注于业务逻辑,而不是重复造轮子。
总之,"SVN64位客户端与服务端"的压缩包为用户提供了完整的64位SVN环境,结合中文语言包和安装文档,使得中国用户能轻松地开始使用这个强大的版本控制系统,从而高效地进行软件开发和团队协作。
Java是开发Zookeeper客户端的主要编程语言之一,因此了解如何在Java中进行Zookeeper的增删改查操作对于开发分布式应用至关重要。 首先,我们需要导入Apache Zookeeper的Java客户端库。这通常通过在项目构建文件(如...
cl 工程是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及服务器编程框架,同时提供更多的实用功能库。通过该库,用户可以非常容易地编写支持多种模式(多线程、多进程、非阻塞、触发器、UDP...
SVN,全称为Subversion,是一种广泛应用于软件开发领域的版本控制系统。它允许团队协作,管理文件和目录的历史,以及跟踪各个版本之间的差异。在本文中,我们将深入探讨SVN的客户端和服务器端安装,以及如何利用汉化...
在这个主题中,我们将深入探讨FTP客户端和服务器的源代码实现,以及如何使用VC++(Visual C++)这种流行的C++开发环境来构建FTP应用。 FTP客户端是用户与FTP服务器交互的软件,它允许用户连接到远程服务器,上传、...
MQTTnet是.NET平台上一个流行的开源库,用于实现MQTT客户端和服务端的功能。 **一、MQTT协议基础** 1. **协议特点**:MQTT协议以小的网络开销、简单易用和双向通信为特点,特别适合资源有限的设备和不稳定网络环境...
VisualSVN资源下载主要涉及的是Subversion(简称SVN)版本控制系统,这是一款在软件开发领域广泛应用的工具,尤其在团队协作中起到了至关重要的作用。SVN允许开发者追踪和控制代码的变化,使得多人同时对同一项目...
标题中的“自己编的SQL服务端加客户端”指的是一个自定义开发的系统,它包括了SQL服务端和客户端两部分。SQL服务端通常是数据库管理系统(DBMS)的一部分,负责处理客户端发送的SQL查询,管理数据库的存储、检索、...