简洁的c++http协议获取内容(一)
使用http协议的好处
1、http协议简单,成熟
2、短链接获取数据后释放
不过在c++中,如果时简单的get 、 post 交互,c++ 不像java,node,或者go那样,随手就写出来,不理解网络包或者没有经验,无非就只能引入包,引入一个包并不难,本来很轻量的程序为了一个两个简单的交互引入越来越多的包并不是好事情,下面我们徒手写一段,可以使用该代码简单地获取数据而不用引入其他包。
http协议 get
int getData(const char* host, unsigned short port, const char* path, const char* get_content){//GET请求方式std::stringstream stream;if(get_content!=NULL && strlen(get_content) > 0)//if (strlen(get_content) > 0)stream << "GET " << path << "?" << get_content;elsestream << "GET " << path;stream << " HTTP/1.0\r\n";stream << "Host: " << host << "\r\n";stream << "User-Agent: cool duck /1.1.1\r\n";stream << "Connection:close\r\n\r\n";//string temp = stream.str();//cout << "len is " << temp.size() << endl;return Http(host, port, stream.str().c_str());}
这段程序使用标准的get 来向服务器获取请求内容,下面show me the code,直接使用socket和缓存获取内容。
int Http(const char* host, unsigned short port, const char *request){SOCKET sockfd;struct sockaddr_in address;struct hostent *server;sockfd = socket(AF_INET, SOCK_STREAM, 0);address.sin_family = AF_INET;address.sin_port = htons(port);//getaddrinfo()server = gethostbyname(host);memcpy((char *)&address.sin_addr.s_addr, (char*)server->h_addr, server->h_length);#ifdef _WIN32int ret = 0;//int timeout = 2000; //2s//这样做在Linux环境下是不会产生效果的,须如下定义:struct timeval timeout = { 2,0 };//设置发送超时setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout, sizeof(struct timeval));//设置接收超时setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout, sizeof(struct timeval));// ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
// ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
#endifif (-1 == connect(sockfd, (struct sockaddr *)&address, sizeof(address))) {#ifdef _WIN32 closesocket(sockfd);
#endifcout << "connection error!" << std::endl;return -1;}#ifdef WIN32int iRes = send(sockfd, request, (int)strlen(request), 0);if (iRes == SOCKET_ERROR) {printf("send failed: %d\n", WSAGetLastError());closesocket(sockfd);return -1;}
#elsestruct timeval timeout = { 2,0 };//2sint ret = setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));int ret = setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));write(sockfd, request, strlen(request));
#endif_data.clear();
#define BUF_SIZE 128char buf[128+1];int offset = 0;int rc;do {int buflen = BUF_SIZE - offset;if (buflen == 0){printf("not enough mem,so continue\n");offset = 0;buflen = BUF_SIZE;//break;}
#ifdef WIN32rc = recv(sockfd, buf + offset, buflen, 0);//rc = recv(sockfd, buf + offset, buflen, MSG_WAITALL);
#elserc = read(sockfd, buf + offset, 1024);
#endifif (rc > 0) {offset += rc;buf[rc] = '\0';_data += buf;printf("Bytes received: %d\n", rc);}else if (rc == 0){printf("Connection closed\n");}elseprintf("recv failed: %d\n",rc);} while (rc > 0);#ifdef WIN32closesocket(sockfd);
#elseclose(sockfd);
#endifcout << _data << endl;}
要点
函数里面定义缓存大小是关键,因为并不知道数据量到底有多大,所以定义为128字节
#define BUF_SIZE 128,写一个nodejs server 来直接返回数据,nodejs代码附在下方
实际上,http协议返回的头部一般都不止128字节,我们使用的量肯定是小的,可以自行修改BUF_SIZE,变大,比如256,甚至更大,在嵌入式系统中,显然字节数目不用过大。
其他:
1、使用循环缓冲来接收字节是比较好的方式,为了方便,直接使用stl的string 来存储接收的值。
2、没有解析所有http头部,实际上结束后可以使用string的find函数来查找字节偏移,得到内容字节数后再获取实际内容
3、如果是用来接收文件,这一段代码要简略修改,首先接收缓冲值要变大,其次不能使用stl string 的相加,可以解析完头部后直接存储写到外部存储中。
结果
调用函数,封装程http_content
int main()
{http_connect conn;conn.getData("127.0.0.1", 8000, "/", NULL);conn.getData("127.0.0.1", 8000, "/test", NULL);getchar();//std::cout << "Hello World!\n";
}
以下为执行结果
图上可以看出,128字节缓存是不够的,分多次获取了数据,第一次get获取数据的时候拿到128字节数据,第二次的时候拿到78字节,流程收到服务器的close信号,直接退出,string 中保存了所有数据,但是需要解析,才能拿到{ret:ok},这个数据
总结
至此已经可以拿到get的数据,虽然简单,但是有效,不用引入额外的库。将在第二篇中讲解解析http头部和获取内容,以及post数据,在往后可以直接解析简单的json数据,而不引入库。
nodejs 服务器
这个就简单了,为了测试而已
var express = require('express');
var app = express();
var http = require('http').Server(app);
var httpget = require('http');
var bodyParser = require('body-parser');
var session = require('express-session');//在线
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json());app.use(session({secret: 'secret',resave: true,// don't save session if unmodifiedsaveUninitialized: false,// don't create session until something storedcookie: {maxAge: 1000 * 60 * 10 //过期时间设置(单位毫秒)}
}));
app.use(express.static(__dirname));
app.get("/",function(req,res){res.send("{ret:ok}");});
app.get("/test",function(req,res){res.send("{ret:test}");
});
app.post("/test",function(req,res){res.send("{ret:test}");});
http.listen(8000, function () {console.log('listening on *:8000');
});
简洁的c++http协议获取内容(一)相关推荐
- 简洁的c++http协议获取内容(二)--获取服务器图片
1 需求 获取http server的图片 用http协议获取server上的图片,前面有文章使用socket直接获取http内容之一,链接如下: 简洁的c++http协议获取内容一 使用简洁的方式目 ...
- androidclient和站点数据交互的实现(基于Http协议获取数据方法)
androidclient一般不直接訪问站点数据库,而是像浏览器一样发送get或者post请求.然后站点返回client能理解的数据格式,client解析这些数据.显示在界面上.经常使用的数据格式是x ...
- 进阶的阿牛哥之用python向多人发送邮件(带附件)、遍历邮件获取内容(两种方法:imbox、imaplib)
(一)向多人发送邮件(带附件) 一.使用的库 这个程序涉及两个库:smtplib 和 email 这两个库都是Python自带的,所以不需要额外的下载安装. 二.思路和步骤 总体思路很简单,就像我们平 ...
- ue html编辑器获取纯文本,百度文本编辑器(Ueditor)怎么获取内容?
百度文本编辑器(Ueditor)是由百度开发的所见即所得文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于BSD协议,允许自由使用和使用代码.那么,Ueditor怎么获取内容呢?不少刚接 ...
- STM32模拟I2C协议获取MLX90615红外温度传感器测温数据(Open Drain管脚配置)
STM32模拟I2C协议获取MLX90615红外温度传感器测温数据(Open Drain管脚配置) STM32的GPIO管脚可以配置为Open Drain输出模式,并且有两个功能: 可以设置内部上拉, ...
- java snmp协议 获取数据
最近工作内容涉及到snmp协议相关内容,由于第一次接触,又没有实际的环境测试,写出来的东西自己都不确定能不能用,直到最近有环境后,花了一段时间才搞定. 写下这篇文章,只是给和我之前一样的小白指点一波, ...
- gatsby_如何使用Gatsby.js来获取内容
gatsby by Dimitri Ivashchuk 由Dimitri Ivashchuk 如何使用Gatsby.js来获取内容 (How to source content with Gatsby ...
- Atitit onvif协议获取rtsp地址播放java语言 attilx总结
Atitit onvif协议获取rtsp地址播放java语言 attilx总结 1.1. 获取rtsp地址的算法与流程1 1.2. Onvif摄像头的发现,ws的发现机制,使用xcf类库1 2. 调用 ...
- php 正则表达式 取所有内容,php正则表达式获取内容所有链接
这篇文章主要介绍了php正则表达式获取内容所有链接的相关资料,需要的朋友可以参考下 方法一: function get_all_url($code){ preg_match_all('/"' ...
最新文章
- php数据库字段类型,mysql 字段类型说明
- 好友国自然基金获批!畅饮之余透露给我这个秘密
- 死而复生?RethinkDB宣布进入Linux基金会!
- leetcode 1306. Jump Game III | 1306. 跳跃游戏 III(BFS)
- No identities are available for signing 的解决办法
- 【立体视觉】双目立体标定与立体校正
- Centos7设置DNS开机启动
- SLAM研究内容框架分析
- 期权、RSU的区别与行权事宜
- 24-java版Spark程序读取ElasticSearch数据
- kali linux引导文件修复,Kali+Windows引导修复
- io里没有driveinfo没有_来福宝宝,愿天堂里没有病痛
- 怎样用调用资源管理器explore.exe打开指定的文件夹
- 经典OA办公协同管理-原型UI设计-制作
- SQLServer To MySQL 解决方案
- SpringBoot实战之文件上传微软云(Azure Storage)
- C语言学习:C语言编译流程
- 国家地表水水质自动监测站坐标位置数据(共1946个点位,含断面名称、所在省份、所在城市、经度、纬度、所在河流、所在流域、断面属性、介绍、属地管理)
- 图像检索算法 TODO
- php strtok函数,strtok函数的用法是什么