登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> 程序员学前班[不再更新,只读] >> 主题: libghttp 一个简单好用的 c++ httpclient 库[linux下,可移植为 win32]     [回主站]     [分站链接]
标题
libghttp 一个简单好用的 c++ httpclient 库[linux下,可移植为 win32]
clq
浏览(0) + 2010-05-19 15:24:17 发表 编辑

关键字:

libghttp 一个简单好用的 c++ httpclient 库[linux下,可移植为 win32]

下载地址: http://lfs.linuxsir.org/htdocs/blfscvs/gnome/libghttp.html
移植方法: http://www.linuxidc.com/Linux/2007-11/9067.htm

把Linux下的http client库移植到windows系统下
[日期:2007-11-16]     来源:Linux公社  作者:rockbeast
今天因为工作需要把linux下面的一个http client库移植到了windows系统下,没想到如此简单。
我改的库是libghttp,如下是我的改写步骤:
首先建立一个空的控制台程序,然后把所有的源代码包含进来,编译。
编译会报告找不到头文件,直接把找不到的头文件去掉,其中有几个网络相关的头文件去掉之后会报告程序编译错误,把WinSock2.h包含进来就可以编译通过了。别的还有就是strcasecmp了,使用strcmp 替代即可,当然有心情的话也可以自己写一个函数替代。
不出意外的话编译就会通过了,链接会出现问题。这里让人有点晕,其实直接把Ws2_32.lib连接进来即可,这个不是默认链接的lib。
写个测试程序,按照ghttp.h里面的接口函数,很快就可以构建起来一个http client,程序怎么写就不说了。编译连接,开始调试。
调试第一个碰到的问题就是gethostbyname返回错误,折磨了我一阵;上网找资料,呵呵,没有添加socket初始化调用,程序开始加上 WSAStartup,结束加上WSACleanup,解决一个。
继续调试,write报告问题,大家都知道linux下网络发送数据使用和文件操作一样的方式,但是windows不一样,使用send替换掉 write,send多一个参数,填个0即可。
再下来出现的问题大家也许就可以猜到了,有write错,就一定有read错,替换成recv,同样给多的一个参数填0;再就是close了,替换成closesocket。
就这么简单,开心啊!可能漏掉一些细节部分,不过基本会写程序的都应该能解决。

clq
2010-5-19 15:26:15 发表 编辑

例子:

一个很好用的http库 -- libghttp
前些时间,由于找不到一个比较好使用的http库,自己封装了一个,不过时间紧迫,也没有完整分析HTTP协议,因此心里总不塌实地使用它,一次偶然的机会,让我在网上找到一个好用的http库 -- libghttp,目前的版本因该是libghttp-1.0.9.
 
这个库十分的方便使用,它能够轻松地实现同步和异步的Http请求。

简单使用实例:

#include <ghttp.h>
int main(int argc, char *argv[])
{
    char *uri = "http://www.hao123.com";
    ghttp_request *request = NULL;
    ghttp_status status;
    char *buf;
    int bytes_read;
  
    request = ghttp_request_new();
    if(ghttp_set_uri(request, uri) == -1)
        exit(-1);
    if(ghttp_set_type(request, ghttp_type_get) == -1)
        exit(-1);
    ghttp_prepare(request);
    status = ghttp_process(request);
    if(status == ghttp_error)
        exit(-1);
    /* OK, done */
    printf("Status code -> %d\n", ghttp_status_code(request));
    buf = ghttp_get_body(loader->request);
    bytes_read = ghttp_get_body_len(loader->request);
    return 0;
}

异步请求实例:

#include <ghttp.h>
int main(int argc, char *argv[])
{
    char *uri = "http://www.hao123.com";
    ghttp_request *request = NULL;
    ghttp_status status;
    char *buf;
    int bytes_read;
  
    request = ghttp_request_new();
    if(ghttp_set_uri(request, uri) == -1)
        exit(-1);
    if(ghttp_set_type(request, ghttp_type_get) == -1)
        exit(-1);
    /* NOTE: Set async request */
    ghttp_set_sync(request, ghttp_async);
    ghttp_prepare(request);
  
    while(1) {
        status = ghttp_process(request);
        if(status == ghttp_error)
            break;
        /* NOTE: buf may NULL, notice it */
        buf = ghttp_get_body(loader->request);
        bytes_read = ghttp_get_body_len(loader->request);
        if(status == ghttp_done) {
            /* NOTE: Ok, done */
            break;
        }
    }
    return 0;
}


文件:libghttp-1.0.9.tar.gz
大小:143KB
下载:下载


clq
2010-5-19 15:32:38 发表 编辑

移植片段:
//windows 下没有 strcasecmp 函数,用 strcmp 代替
#if WIN32
    #ifndef strcasecmp
    #define strcasecmp strcmp
    #endif
#endif


#if WIN32
    #include <sys/types.h>
    #include <WinSock2.h>
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>

#endif

closesocket(a_conn->sock);//clq win32//close(a_conn->sock);

  //--------------------------------------------------
  //clq 这里 win32 下差别比较大,重写一下
  /* read in some data */
  /*
  if ((a_conn->last_read = l_read = read(a_conn->sock,
                     &a_conn->io_buf[a_conn->io_buf_alloc],
                     l_bytes_to_read)) < 0)
    {
      if (errno == EINTR)
    l_read = 0;
      else
    return HTTP_TRANS_ERR;
    }
  else if (l_read == 0)
    return HTTP_TRANS_DONE;
  */

    if ((a_conn->last_read = l_read = recv(a_conn->sock, &a_conn->io_buf[a_conn->io_buf_alloc], l_bytes_to_read, 0)) < 0)
    {
        //if (errno == EINTR)
        //    l_read = 0;
        //else
            return HTTP_TRANS_ERR;
    }
    else
    if (l_read == 0)
    {
        return HTTP_TRANS_DONE;
    }


  //--------------------------------------------------


  //--------------------------------------------------
  //clq 这里 win32 下差别比较大,重写一下
  /* write out some data */
  /*
  if ((a_conn->last_read = l_written = write (a_conn->sock,
                          &a_conn->io_buf[a_conn->io_buf_io_done],
                          a_conn->io_buf_io_left)) <= 0)
    {
      if (errno == EINTR)
    l_written = 0;
      else
    return HTTP_TRANS_ERR;
    }
  if (l_written == 0)
    return HTTP_TRANS_DONE;
  */

    if ((a_conn->last_read = l_written = send(a_conn->sock,    &a_conn->io_buf[a_conn->io_buf_io_done], a_conn->io_buf_io_left, 0)) <= 0)
    {
        //if (errno == EINTR)
        //l_written = 0;
        //else
        return HTTP_TRANS_ERR;
    }
    if (l_written == 0)
        return HTTP_TRANS_DONE;


  //--------------------------------------------------



clq
2010-5-19 15:52:20 发表 编辑

本来想看看 php 里用的是啥照抄一下. 不过 php 有自己的 httpclient 类,另外也有人直接用 curl 库,或者是在 curl 上封装的一个库. curl 多年前用过印象非常之不好,所以罢了. php 自身库的用法如下:

HttpClient php类库
2010-04-09 17:45

GET行为比较简单,POST比较复杂一些。这里提供两种方法供选择:

第一:手写代码
第二:利用HttpClient php类库

第一种方法:代码如下:
<?PHP      
    $flag = 0;  
    //要post的数据   
$argv = array(  
     'var1'=>'abc',   
     'var2'=>'你好吗');   
//构造要post的字符串   
foreach ($argv as $key=>$value) {   
     if ($flag!=0) {  
             $params .= "&";   
             $flag = 1;   
     }   
     $params.= $key."="; $params.= urlencode($value);   
     $flag = 1;   
     }   
     $length = strlen($params);  
         //创建socket连接   
     $fp = fsockopen("127.0.0.1",80,$errno,$errstr,10) or exit($errstr."--->".$errno);   
     //构造post请求的头   
     $header = "POST /mobile/try.php HTTP/1.1";   
     $header .= "Host:127.0.0.1";   
     $header .= "Referer:/mobile/sendpost.php";   
     $header .= "Content-Type: application/x-www-form-urlencoded";   
     $header .= "Content-Length: ".$length."";   
     $header .= "Connection: Close";  
     //添加post的字符串   
     $header .= $params."";   
     //发送post的数据   
     fputs($fp,$header);   
     $inheader = 1;   
     while (!feof($fp)) {  
             $line = fgets($fp,1024); //去除请求包的头只显示页面的返回数据   
             if ($inheader && ($line == "\n" || $line == "")) {  
                 $inheader = 0;   
             }   
             if ($inheader == 0) {   
                 echo $line;   
             }   
     }   
fclose($fp);   
?>

第二种方法是:使用httpclient类,代码如下:
$pageContents = HttpClient::quickPost('http://example.com/someForm', array(  
    'name' => 'Some Name',  
    'email' => 'email@example.com' 
));

使用附件的类库,也可以去官方下载最新的类库,官方地址为:http://scripts.incutio.com/httpclient/index.php
附加一些php httpclient的其他几个用法
静态方法获取网页
$pageContents = HttpClient::quickGet('http://example.com/');

Get方法获取
$client = new HttpClient('example.com');  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

带调试的Get方法获取
$client = new HttpClient('example.com');  
$client->setDebug(true);  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

带自动转向的Get方法
$client = new HttpClient('www.amazon.com');  
$client->setDebug(true);  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

检查页面是否存在
$client = new HttpClient('example.com');  
$client->setDebug(true);  
if (!$client->get('/thispagedoesnotexist')) {  
    die('An error occurred: '.$client->getError());  
}  
if ($client->getStatus() == '404') {  
    echo 'Page does not exist!';  
}  
$pageContents = $client->getContent();

伪造客户端
$client = new HttpClient('example.com');  
$client->setDebug(true);  
$client->setUserAgent('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.3a) Gecko/20021207');  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

登录验证并请求一个网页
$client = new HttpClient('example.com');  
$client->post('/login.php', array(  
    'username' => 'Simon',  
    'password' => 'ducks' 
));  
if (!$client->get('/private.php')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

HTTP授权
$client = new HttpClient('example.com');  
$client->setAuthorization('Username', 'Password');  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
$pageContents = $client->getContent();

输出头信息
$client = new HttpClient('example.com');  
if (!$client->get('/')) {  
    die('An error occurred: '.$client->getError());  
}  
print_r($client->getHeaders());

设置一个域内重定向最多次数
$client = new HttpClient('www.amazon.com');  
$client->setDebug(true);  
$client->setMaxRedirects(3);  
$client->get('/');


总数:3 页次:1/1 首页 尾页  
总数:3 页次:1/1 首页 尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1