libevent(十四)http client 请求 (GET、POST)

本文依赖于 libevent(十三)http server,服务端开启服务,客户端进行请求:
如下代码共四个函数:
void http_client_cb(struct evhttp_request* req, void* ctx) 回调函数 接受服务端信息并处理
int TestGetHttp() 进行GET请求
int TestPostHttp()进行POST请求
int main(int argc, char** argv) 主函数

#include <iostream>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/keyvalq_struct.h>
#include <event2/buffer.h>
#include <event2/util.h>
#include <event2/bufferevent.h>
#include <string.h>
#include <string>
#include <event2/listener.h>
#define SPORT 5001
#ifndef _WIN32
#include <signal.h>
#endif
using namespace std;


void http_client_cb(struct evhttp_request* req, void* ctx) {
	cout << ">>>>>http_client_cb>>>>>" << endl;
	event_base* base = (event_base *)ctx;
	
	//服务端响应错误
	if (req == NULL)
	{
		int err_code = EVUTIL_SOCKET_ERROR();
		cout << "socket_error " << evutil_socket_error_to_string(err_code) << endl;
		return;
	}

	//获取path
	const char* path = evhttp_request_get_uri(req);
	cout << "request path is " << path << endl;
	string filepath = ".";
	filepath += path;
	//若路径中有目录,需要手动创建
	cout << "filepath is " << filepath << endl;
	FILE* fp = fopen(filepath.c_str(), "wb");
	if (!fp)
	{
		cout << "open filepath " << filepath << " failed!" << endl;
	}

	//获取返回的code 200 OK  404/NOT Found 500等
	cout << "Response is 200? :" << evhttp_request_get_response_code(req) << endl;
	cout << "Response is OK? :" << evhttp_request_get_response_code_line(req) << endl;

	evbuffer* input = evhttp_request_get_input_buffer(req);
	char buf[1024] = { 0 };
	for (;;)
	{
		int len = evbuffer_remove(input, buf, sizeof(buf) - 1);
		if (len <= 0)break;
		buf[len] = 0;
		if (!fp)continue;
		fwrite(buf, 1, len, fp);
		//cout << "print all html = buf "<< buf << endl; 
	}
	if (fp)fclose(fp);
	event_base_loopbreak(base);
	cout << "file save success!" << endl; 
}


int TestGetHttp() {
	event_base* base = event_base_new();
	if (base) {
		std::cout << "event_base_new init successfuly!" << std::endl;
	}

	//http 服务器
	//1. 创建evhttp上下文
	evhttp* evh = evhttp_new(base);

	//2. 生成请求信息:GET
	string http_url = "http://ffmpeg.club/index.html?id=1&name=2";
	http_url = "http://ffmpeg.club/lesson_img/101.jpg";

	// 分析url地址//
	// uri
	evhttp_uri* uri = evhttp_uri_parse(http_url.c_str());
	const char* scheme = evhttp_uri_get_scheme(uri);
	if (!scheme)
	{
		cerr << "scheme is NULL" << endl;
		return -1;
	}
	cout << "scheme is http? =>" << scheme << endl;

	//port 
	int port = evhttp_uri_get_port(uri);
	if (port < 0)
	{
		if (strcmp(scheme, "http") == 0)
		{
			port = 80;
		}
	}
	cout << "port is " << port << endl;

	//host = ffmpeg.club
	const char* host = evhttp_uri_get_host(uri);
	if (!host)
	{
		cerr << "host is NULL" << endl;
		return -1;
	}
	cout << "host is ffmpeg.club? =>" << host << endl;

	const char* path = evhttp_uri_get_path(uri);
	if (!path || strlen(path) == 0)
	{
		path = "/";
	}
	if (path)
	{
		cout << "path is /index.html? =>" << path << endl;
	}

	//url 传参分析:?后面的内容
	const char* query = evhttp_uri_get_query(uri);
	if (query)
	{
		cout << "query is " << query << endl;
	}
	else
	{
		cout << "query is NULL" << endl;
	}

	//bufferevent 连接http服务器
	bufferevent* bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
	evhttp_connection* ev_conn = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port);

	//http client 请求 回调函数设置
	evhttp_request* req = evhttp_request_new(http_client_cb, base);

	//设置请求header信息
	evkeyvalq* output_header = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_header, "Host", host);

	//发起请求
	evhttp_make_request(ev_conn, req, EVHTTP_REQ_GET, path);

	// 事件分发处理
	if (base) {
		event_base_dispatch(base);
	}
	if (base) {
		event_base_free(base);
	}
}


int TestPostHttp() {
	event_base* base = event_base_new();
	if (base) {
		std::cout << "event_base_new init successfuly!" << std::endl;
	}

	//http 服务器
	//1. 创建evhttp上下文
	evhttp* evh = evhttp_new(base);

	//2. 生成请求信息:GET
	string http_url = "http://192.168.140.139:8080/index.html";

	// 分析url地址//
	// uri
	evhttp_uri* uri = evhttp_uri_parse(http_url.c_str());
	const char* scheme = evhttp_uri_get_scheme(uri);
	if (!scheme)
	{
		cerr << "scheme is NULL" << endl;
		return -1;
	}
	cout << "scheme is http? =>" << scheme << endl;

	//port 
	int port = evhttp_uri_get_port(uri);
	if (port < 0)
	{
		if (strcmp(scheme, "http") == 0)
		{
			port = 80;
		}
	}
	cout << "port is " << port << endl;

	//host = ffmpeg.club
	const char* host = evhttp_uri_get_host(uri);
	if (!host)
	{
		cerr << "host is NULL" << endl;
		return -1;
	}
	cout << "host is ffmpeg.club? =>" << host << endl;

	const char* path = evhttp_uri_get_path(uri);
	if (!path || strlen(path) == 0)
	{
		path = "/";
	}
	if (path)
	{
		cout << "path is /index.html? =>" << path << endl;
	}

	//url 传参分析:?后面的内容
	const char* query = evhttp_uri_get_query(uri);
	if (query)
	{
		cout << "query is " << query << endl;
	}
	else
	{
		cout << "query is NULL" << endl;
	}

	//bufferevent 连接http服务器
	bufferevent* bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
	evhttp_connection* ev_conn = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port);

	//http client 请求 回调函数设置
	evhttp_request* req = evhttp_request_new(http_client_cb, base);

	//设置请求header信息
	evkeyvalq* output_header = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_header, "Host", host);

	//发送post数据
	evbuffer* output = evhttp_request_get_output_buffer(req);
	evbuffer_add_printf(output, "test_post_request=%d&name=%d", 1, 2);

	//发起请求
	evhttp_make_request(ev_conn, req, EVHTTP_REQ_POST, path);

	// 事件分发处理
	if (base) {
		event_base_dispatch(base);
	}
	if (base) {
		event_base_free(base);
	}
}


int main(int argc, char** argv) {
#if _WIN32
	//windowns 初始化socket库
	WSADATA wsa;
	WSAStartup(MAKEWORD(2, 2), &wsa);
#else
	//linux 忽略管道信号,发送数据给已关闭的socket
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		return 1;
#endif
	TestGetHttp();
	cout << "========== Test TestGetHttp client! ========" << endl;

	TestPostHttp();
	cout << "========== Test TestPostHttp client! ========" << endl;

#ifdef _WIN32
	WSACleanup();
#endif // _WIN32
	return 0;
}

客户端信息:
在这里插入图片描述

服务端信息:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值