标题
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
例子:
一个很好用的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
移植片段:
//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
本来想看看 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('/');
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.