专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » 点击这里:使用 cURL 和 libcurl 通过 Internet 进行对话: 将 libcurl 和 C 以及 Python 结合使用 »正文

点击这里:使用 cURL 和 libcurl 通过 Internet 进行对话: 将 libcurl 和 C 以及 Python 结合使用

来源: 发布时间:星期一, 2009年11月30日 浏览:78次 评论:0
  开发 HTTP 和 FTP 的类依赖于应用层协议应用并不复杂但也不简单步讲这不是应用重点大部分情况下协议的上内容才是真正重要内容因此libcurl 引起了许多人兴趣重点是应用而不是开发各个方面注意很少有应用开发自己 TCP/IP 堆栈所以老话重提:尽可能重用以最小化开发安排并提高应用可靠性

  本文首先简单介绍应用层协议然后介绍 cURL、libcurl 并解释它们使用方法

  Web 协议

  如今构建应用已和过去大不相同现在应用需要能够通过网络或 Internet 进行通讯(提供人类可用网络 API 或接口)还要能支持用户脚本化以提高灵活性现代应用通常使用 HTTP 公开 Web 接口并通过 Simple Mail Transport Protocol (SMTP) 提供警告通知这些协议允许您将 Web 浏览器指向设备以获得配置或状态信息并从设备或常用电子邮件客户端接收标准电子邮件(分别通过 HTTP 和 SMTP)

  这些 Web 服务通常构建在网络堆栈套接字层上(见图 1)套接字层实现个最先出现在 Berkeley Software Distribution (BSD) 操作系统上 API并提取底层传输和网络层协议详细信息


图 1. 网络堆栈和 libcurl




  Web 服务发生在客户端和服务器的间协议对话中在 HTTP 上下文中服务器是终端设备客户端是位于端点上浏览器对于 SMTP服务器是邮件网关或端点用户客户端是终端设备在某些情况下协议对话发生在两个步骤(请求和响应)中但另些情况下需要协商和通讯通信量更多这种协商可能增加了大量复杂性这可以通过 API 进行抽象比如 libcurl

  cURL 介绍

  cURL 起源和发展
cURL 是 Daniel Stenberg 发明但是 600 多名开发人员也做出了巨大贡献它无疑是许多应用都使用有用技术的

  cURL 最初设计初衷是使用区别协议(比如 FTP、HTTP、SCP 等)在端点的间移动文件它最初是个命令行实用工具但现在也是个绑定了 30 多种语言因此现在不仅可以通过 shell 使用 cURL您还可以构建合并了这个重要功能应用libcurl 库也是可以移植支持 Linux®、IBM®AIX®操作系统、BSD、Solaris 以及许多其他 UNIX®变体

  获取和安装 cURL/libcurl

  获取和安装 libcurl 非常简单取决于您所运行 Linux 发行版如果运行是 Ubuntu您可以使用 apt-get轻松安装这些包以下行演示了如何为 libcurl 安装 libcurl 和 Python 绑定:

 $ sudo apt-get  libcurl3 
 $ sudo apt-get  python-pycurl 


  apt-get实用工具确保该过程满足所有依赖关系

  在命令行中使用 cURL

  cURL 最开始是个命令行工具可以使用 Unorm Resource Locator (URL) 语法执行数据传输考虑到它在命令行上流行度后来创建了个可以在应用中生成这些行为如今命令行 cURL 是 cURL 库包装器本文首先研究 cURL 作为命令行功能然后深入探讨如何将它作为库使用

  cURL 两种常见使用方法是使用 HTTP 和 FTP 协议进行文件传输cURL 为这些协议提供个简单接口要使用 HTTP 从网站WebSite获取文件只需告诉 cURL 您要将网页写入到其中本地文件文件名、网站WebSite URL 以及要获取文件让我们看下清单 1 中简单命令行举例


清单 1. 使用 cURL 从网站WebSite获取文件举例
 $ curl -o test html www.exampledo.com 
 % Total  % Received % Xferd Average Speed  Time  Time   Time  Current 
                 Dload Upload  Total  Spent  Left  Speed 
 100 43320 100 43320  0   0 55831    0 --:--:-- --:--:-- --:--:-- 89299 
 $ 


  注意由于我指定了域而不是文件我将获得根文件(index.html)要使用 cURL 将该文件移动到 FTP 站点可以使用 -T选项指定要上传文件然后提供 FTP 站点 URL 以及文件路径


清单 2. 使用 cURL 将文件上传到 FTP 站点举例
 $ curl -T test.html ftp://user:[email protected].com/ftpdir/ 
 % Total  % Received % Xferd Average Speed  Time  Time   Time  Current 
                 Dload Upload  Total  Spent  Left  Speed 
 100 43320  0   0 100 43320   0 38946  0:00:01 0:00:01 --:--:--  124k 
 $ 


  是不是很简单?学习了些模式的后您会发现cURL 使用起来非常简单但是您可以使用选项非常多 —在 cURL 命令行中请求帮助(使用 --help)可以得到 129 行选项如果您觉得这还不算太多那么还有大批其他控制选项(从详细度到安全性)以及特定于协议配置项

  从开发人员角度看这还不算是 cURL 最令人兴奋地方让我们深入了解 cURL 库学习如何向应用添加文件传输协议

  作为库 cURL

  如果您有 10 年以上脚本语言经验您就会注意到它们标记有很大变化Python、Ruby、Perl 等这些脚本语言不仅包含套接字层(C 或 C 中也有)还包含了应用层协议 API这些脚本语言合并了高级功能可以创建 HTTP 服务器或客户端libcurl 库为 C 和 C 的类语言添加了类似功能但是它可以在区别语言的间移植在所有它支持语言中都能找到和 libcurl 相当行为但是由于这些语言差异很大(设想下 C 和 Scheme)提供这些行为方式也很不相同

  libcurl 库以 API 形式封装清单 1和清单 2中描述行为因此它可以被高级语言使用(如今已超过 30 种)本文提供了 libcurl 两个举例个举例研究使用 c 构建简单 HTTP 客户端(适合构建 Web 爬行器)第 2个举例是个使用 Python 创建简单 HTTP 客户端

  基于 C HTTP 客户端

  C API 在 libcurl 功能上提供了两个 APIeasy 接口是个简单同步 API(意味着当您使用请求 libcurl 时将能够满足您请求直到完成或发生)多接口可以进步控制 libcurl应用可以执行多个同步传输并控制 libcurl 何时何地移动数据

  该举例使用 easy 接口该 API 还能控制数据移动过程(使用回调)但正如其名称所示使用起来非常简单清单 3 提供了 HTTP C 语言举例


清单 3. 使用 libcurl easy 接口 C HTTP 客户端
 # <stdio.h> 
 # <.h> 
 # <curl/curl.h> 
 
 # MAX_BUF  65536 
 
 char wr_buf[MAX_BUF+1]; 
  wr_index; 
 
 /* 
 * Write data callback function (called within the context of 
 * curl_easy_perform. 
 */ 
 size_t write_data( void *buffer, size_t size, size_t nmemb, void *userp ) 
 { 
  segsize = size * nmemb; 
 
 /* Check to see  this data exceeds the size of our buffer. If so, 
  *  the user-d context value and  0 to indicate a 
  * problem to curl. 
  */ 
  ( wr_index + segsize > MAX_BUF ) { 
  *( *)userp = 1; 
   0; 
 } 
 
 /* Copy the data from the curl buffer o our buffer */ 
 memcpy( (void *)&wr_buf[wr_index], buffer, (size_t)segsize ); 
 
 /* Update the write index */ 
 wr_index  segsize; 
 
 /* Null terminate the buffer */ 
 wr_buf[wr_index] = 0; 
 
 /* Return the number of s received, indicating to curl that all is okay */ 
  segsize; 
 } 
 
 
 /* 
 * Simple curl application to read the index.html file from a Web site. 
 */ 
  ( void ) 
 { 
 CURL *curl; 
 CURLcode ret; 
  wr_error; 
 
 wr_error = 0; 
 wr_index = 0; 
 
 /* First step, init curl */ 
 curl = curl_easy_init; 
  (!curl) { 
  prf("couldn't init curl\n"); 
   0; 
 } 
 
 /* Tell curl the URL of the file we're going to retrieve */ 
 curl_easy_opt( curl, CURLOPT_URL, "www.exampledo.com" ); 
 
 /* Tell curl that we'll receive data to the function write_data, and 
  * also provide it with a context poer for our error . 
  */ 
 curl_easy_opt( curl, CURLOPT_WRITEDATA, (void *)&wr_error ); 
 curl_easy_opt( curl, CURLOPT_WRITEFUNCTION, write_data ); 
 
 /* Allow curl to perform the action */ 
 ret = curl_easy_perform( curl ); 
 
 prf( "ret = %d (write_error = %d)\n", ret, wr_error ); 
 
 /* Emit the page  curl indicates that no errors occurred */ 
  ( ret  0 ) prf( "%s\n", wr_buf ); 
 
 curl_easy_cleanup( curl ); 
 
  0; 
 } 


  最上方是必需 文件包括 cURL 根文件接下来我定义了两个用于传输变量个变量是 wr_buf表示将在其中写入传入数据缓冲区wr_index表示缓冲区当前写入索引

  转到 使用 easy API 进行设置所有 cURL 都通过维护特定请求状态句柄进行操作这称为 CURL指针引用本例还创建个特殊返回码称为 CURLcode在使用任何 libcurl 的前您需要 curl_easy_init获取 CURL句柄接下来注意 curl_easy_opt数量它们为特定操作配置句柄对于这些您提供句柄、命令和选项首先本例使用 CURLOPT_URL指定要获取 URL然后它使用 CURL_WRITEDATA提供个上下文变量(在本例中它是内部 write 变量)最后它使用 CURLOPT_WRITEFUNCTION指定数据可用时应该在启动 API 的后API 将使用它读取数据多次

  要开始传输 curl_easy_perform工作是根据的前配置执行传输在完成传输或发生的前该不会返回最后步是提交返回状态提交页面读取最后使用 curl_easy_cleanup清除(当使用句柄执行完操作后)

  现在看看 write_data是针对特定操作收到数据时回调注意当您从网站WebSite读取数据时将写入该数据(write_data)将向回调提供个缓冲区(包含可用数据)、成员数量和大小(缓冲中可用数据总量)、上下文指针个任务是确保缓冲区(wr_buf)空间足以写入数据如果不够它将设置上下文指针并返回 0表示出现问题否则它将 cURL 缓冲区数据复制到您缓冲区并增加索引指向要写入个位置本例还终止稍后可以对其使用 prf最后它返回 libcurl 操作字节数量这将告诉 libcurl 数据被提取它也可以丢弃该数据这就是从网站WebSite将文件读取到内存相对简单思路方法

  基于 Python HTTP 客户端

  本节提供举例类似于基于 C HTTP 客户端不过它使用是 PythonPython 是种非常有用面向对象脚本语言在原型化和构建生产软件Software方面非常突出举例假设您较熟悉 Python但使用不多因此不要期望过高

  这个简单 Python HTTP 客户端使用 pycurl如清单 4 所示


清单 4. 使用 libcurl pycurl接口 Python HTTP 客户端
 import sys 
 import pycurl 
 
 wr_buf = '' 
 
 def write_data( buf ): 
 global wr_buf 
 wr_buf  buf 
 
 def : 
 c = pycurl.Curl 
 c.opt( pycurl.URL, 'http://www.exampledo.com' ) 
 c.opt( pycurl.WRITEFUNCTION, write_data ) 
 
 c.perform 
 
 c.close 
 
  
 sys.stdout.write(wr_buf) 

使用 Python 进行原型化

  原型化是 Python 优势的它只需很少代码就可以实现大量功能使用 C 也许能获得更好性能但是如果您是快速编码以证明某个概念那么高级脚本语言是无可替代比如 Python

  这比 C 语言版本简单它首先导入必需模块(用于标准系统 sys和 pycurl模块)接下来它定义 write 缓冲区(wr_buf)像 C 我声明个 write_data注意只有个参数:从 HTTP 服务器中读取数据缓冲区我将该缓冲区连接到全局 write 缓冲区首先创建个 Curl句柄然后使用 opt思路方法为传输定义 URL和 WRITEFUNCTION perform思路方法启动传输并关闭句柄最后 并将 write 缓冲区提交到 stdout注意在这种情况下您不需要上下文指针您使用了 Python 串连接这就是说您不会使用大小固定



  结束语

  本文仅仅简单介绍了 libcurl介绍了它支持多种协议和语言希望这能够展示它如何轻松构建使用应用层协议(如 HTTP)应用libcurl 网站WebSite提供了很多举例和有用文档次开发 Web 浏览器、爬行器或其他有应用层协议要求应用试试 libcurl定能大大减少您开发时间并找回编码乐趣



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: