Poco库使用:使用http协议通信

搭建HTTP服务端

搭建HTTP服务端,主要用到三个类分别是:HTTPServer、HTTPRequestHandlerFactory、HTTPRequestHandler。HTTPServer负责监听特定的端口接收数据,接收的数据传递给HTTPRequestHandlerFactory,HTTPRequestHandlerFactory通过解析请求的参数在独立的线程中生成HTTPRequestHandler负责对每个独立的请求进行处理。服务端的搭建方法如下所示:

1.在主应用中启动HTTP服务

//MyHttpServer.h
#include "Poco/Util/ServerApplication.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Logger.h"

using namespace Poco;
using Poco::Util::ServerApplication;
using Poco::Net::HTTPServer;
using Poco::Net::ServerSocket;

class HttpApplication: public ServerApplication {
public:
    HttpApplication(){ }
    ~HttpApplication() { }
protected:
    //初始化操作
    void initialize(Application& self);
    //清理操作
    void uninitialize();
    //主函数入口
    int main(const vector<string>& args);
private:
    //http监听服务
    HTTPServer * _httpSvr;
};
//MyHttpServer.cpp
#include "MyHttpServer.h"
void HttpApplication::initialize(Application& self) {
    loadConfiguration();
    ServerApplication::initialize(self);
}

void HttpApplication::uninitialize() {
    ServerApplication::uninitialize();
}

int HttpApplication::main(const vector<string>& args) 
{
    //可以指定固定的端口也可以从外部配置
    int port = 9876;
    ServerSocket svs(port);
    _httpSvr = new HTTPServer(new MyHTTPHandlerFactory(), svs, new HTTPServerParams);
    _httpSvr->start();
    //阻塞住进程
    waitForTerminationRequest();
    return Application::EXIT_OK;
}

2.在工厂类中处理请求

在工厂类中根据请求参数,区分不同的请求,然后生成对应的处理类。

//MyHttpHandlerFactory.h
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPRequestHandler.h"

using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPRequestHandler;

class MyHTTPHandlerFactory : public HTTPRequestHandlerFactory {
public:
    HTTPRouteHandlerFactory(){};
    ~HTTPRouteHandlerFactory(){};
    HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request);
};
//MyHttpHandlerFactory.cpp
#include "MyHttpHandlerFactory.h"
#include "Poco/URI.h"
using Poco::URI;

HTTPRequestHandler * MyHTTPHandlerFactory::createRequestHandler(const HTTPServerRequest & request)
{
	if (request.getURI() == "/echoBody")
		return new EchoBodyRequestHandler;
	else if (request.getURI() == "/echoHeader")
		return new EchoHeaderRequestHandler;
	else if (request.getURI() == "/redirect")
		return new RedirectRequestHandler;
	else if (request.getURI() == "/auth")
		return new AuthRequestHandler;
	else if (request.getURI() == "/buffer")
		return new BufferRequestHandler;
	else if (request.getURI() == "/trailer")
		return new TrailerRequestHandler;
	else
		return 0;
}

3.定义业务处理类

针对特定的业务请求,定义继承自HTTPRequestHandler的业务处理类。在特定的业务类中处理请求并响应。例子来源于官方示例。

#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPServerRequest.h"

using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerRequest;
using Poco::Logger;

class EchoBodyRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		if (request.getChunkedTransferEncoding())
			response.setChunkedTransferEncoding(true);
		else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
			response.setContentLength(request.getContentLength());

		response.setContentType(request.getContentType());

		std::istream& istr = request.stream();
		std::ostream& ostr = response.send();
		StreamCopier::copyStream(istr, ostr);
	}
};

class EchoHeaderRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		std::ostringstream osstr;
		request.write(osstr);
		int n = (int) osstr.str().length();
		response.setContentLength(n);
		std::ostream& ostr = response.send();
		if (request.getMethod() != HTTPRequest::HTTP_HEAD)
			request.write(ostr);
	}
};

class RedirectRequestHandler: public AbstractHTTPRequestHandler
{
public:
	void run()
	{
      response().redirect("http://www.appinf.com/");
	}
};

class AuthRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		response.requireAuthentication("/auth");
		response.send();
	}
};

class BufferRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		std::string data("xxxxxxxxxx");
		response.sendBuffer(data.data(), data.length());
	}
};

class TrailerRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		std::string data("xxxxxxxxxx");

		response.setChunkedTransferEncoding(true);
		Poco::Net::MessageHeader& trailer = static_cast<Poco::Net::HTTPServerRequestImpl&>(request).session().responseTrailer();
		trailer.set("Trailer-1", "Value 1");
		trailer.set("Trailer-2", "Value 2");
		response.send() << data;
	}
};

4.解析请求参数

http业务请求中通常会包含一些请求参数,这里介绍一下请求参数的解析方法。

class AuthRequestHandler: public HTTPRequestHandler
{
public:
	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
       try
       {
            //解析请求表单中的参数
            HTMLForm format(request);
            if (format.has("paramer1"))
           {
                std::string paramer1 = format.get("paramer1");
           }
           
           //解析http Content中的json数据
           std::istream& istr = request.stream();
           //判断内容是不是json,不是的话返回错误
		if (request.getContentType() != std::string("application/json"))
		{
                   //handle not json error
			return;
		}
            //读取json数据
		int content_length = (int)request.getContentLength();
		char* request_content = new char[content_length + 1];
		memset(request_content, 0x00, content_length + 1);
		istr.read(request_content, content_length);
		std::string my_request_str(request_content, content_length);
           //释放分配的内存
		if (request_content)
		{
              delete[] request_content;
		}
		//解析JSON内容
		JSON::Parser parser;
		Dynamic::Var  result;
		result = parser.parse(my_request_str);
		JSON::Object::Ptr object_ptr = result.extract<JSON::Object::Ptr>();
           if (object_ptr->has("paramer1"))
           {
                std::string paramer1 = object_ptr->get("paramer1").toString();
           }
           
       }
       catch (Poco::Exception& e)
       {
		//handle exception 
	    }
	}
};

5.返回响应结果

将执行结果数据以json的形式反馈给客户端。

void AuthRequestHandler::sendResponseResult(HTTPServerRequest & request, HTTPServerResponse & response, 
std::string result_info)
{
	bool _bEnc = request.getChunkedTransferEncoding();
	response.setChunkedTransferEncoding(_bEnc);
    //设置内容格式为json
	response.setContentType("application/json");
    //允许跨域访问
	response.add("Access-Control-Allow-Origin", "*");
	response.add("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE");
	response.add("Access-Control-Max-Age", "3600");
	response.add("Access-Control-Allow-Headers", "x-requested-with,content-type");
	response.add("Access-Control-Allow-Credentials", "true");
    //响应反馈数据
	std::ostream& response_stream = response.send();
	response_stream << result_info;
	response_stream.flush();
}

HTTP客户端请求

1.发送GET请求

bool SendGetRequest()
{
    //请求的参数
    std::string arg1 = "1";
    std::string arg2 = "2";
    std::string arg3 = "3";

    //请求路径
    std::string path = "/api/v1/get_request";
    
    //设定服务器的地址
    Poco::URI uri;
    uri.setScheme("http");
    uri.setHost("127.0.0.1");
    uri.setPort(8800);
    uri.setPath(path);
    
    //添加请求参数
    uri.addQueryParameter("arg1", arg1);
    uri.addQueryParameter("arg2", arg2);
	 uri.addQueryParameter("arg3", arg3);
  
    //定义客户端
     Poco::Net::HTTPClientSession* http_session = 
    new HTTPClientSession();
	 http_session->setPort(uri.getPort());
	 http_session->setHost(uri.getHost());
  
    //定义GET请求
    std::string pathAndQuery(uri.getPathAndQuery());
    Poco::Net::HTTPRequest request(
        Poco::Net::HTTPRequest::HTTP_GET, pathAndQuery,
        Poco::Net::HTTPMessage::HTTP_1_1);
        
    //发送请求等待响应    
    Poco::Net::HTTPResponse response;
	http_session->sendRequest(request);
    std::istream &streamIn = http_session->receiveResponse(response);
    
    //获取响应内容
    std::ostringstream responseStream;
    Poco::StreamCopier::copyStream(streamIn, responseStream);
    std::string = responseContent = responseStream.str();
    
    //释放资源
	delete https_session;
	https_session = nullptr;
    return response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK;
}

2.发送POST请求

int sendPostRequest()
{
	try
	{
            //指定服务器地址和访问路径
		std::string path = "/api/v1/post_request";
		Poco::URI uri;
		uri.setScheme("http");
		uri.setHost("127.0.0.1");
		uri.setPort(8800);
		uri.setPath(path);
           //定义客户端
           Poco::Net::HTTPClientSession* http_session = 
              new HTTPClientSession();
		http_session->setHost(uri.getHost());
		http_session->setPort(uri.getPort());
           //定义POST请求
		Poco::Net::HTTPRequest request(
			Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(),
			Poco::Net::HTTPMessage::HTTP_1_1);
           //添加请求参数
		Poco::Net::HTMLForm form;
		form.add("arg1", "1");
		form.add("arg2", "2");
		form.add("arg3", "3");
		form.prepareSubmit(request);
           //发送请求等待响应
		form.write(http_session->sendRequest(request));
		Poco::Net::HTTPResponse response;
		std::istream &streamIn = http_session->receiveResponse(response);

		if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
		{
			delete http_session;
			http_session = nullptr;
			return 1;
		}
            //获取响应结果
		std::ostringstream responseStream;
		Poco::StreamCopier::copyStream(streamIn, responseStream);
		std::string resultStr = responseStream.str();

		delete http_session;
		http_session = nullptr;
           //解析反馈的json结果
		Poco::JSON::Parser parser;
		auto root = parser.parse(resultStr);
		Poco::JSON::Object::Ptr objRoot = root.extract<Poco::JSON::Object::Ptr>();

		int codeResult = objRoot->getValue<int>("code");
		if (codeResult == 200)
		{
		}
		return codeResult;
	}
	catch (Poco::Exception& e)
	{
      //处理异常
	}
}    

3.发送MultiPart Post请求

int sendMutiPartRequest()
{
	try
	{
             //请求路径和服务器配置
		std::string path = "/api/v1/multipart";
		Poco::URI uri;
		uri.setScheme("http");
		uri.setHost("127.0.0.1");
		uri.setPort(8800);
		uri.setPath(path);

		 //定义客户端
           Poco::Net::HTTPClientSession* http_session = 
              new HTTPClientSession();
		http_session->setHost(uri.getHost());
		http_session->setPort(uri.getPort());
            
            //生成对应的请求
		Poco::Net::HTTPRequest request(
			Poco::Net::HTTPRequest::HTTP_POST, uri.getPathAndQuery(),
			Poco::Net::HTTPMessage::HTTP_1_1);
		request.setContentType("multipart/form-data");
            
            //在表单中添加对应的参数和文件
		Poco::Net::HTMLForm form;
		form.setEncoding(Poco::Net::HTMLForm::ENCODING_MULTIPART);
		form.add("arg1", "1");
		form.add("arg2", "2");
		form.add("arg3", "3");
		form.addPart("file", new Poco::Net::FilePartSource(filePath));
		form.prepareSubmit(request);
           //发送请求等待响应
		form.write(http_session->sendRequest(request));
		Poco::Net::HTTPResponse response;
		std::istream &streamIn = http_session->receiveResponse(response);

  		if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
		{
			delete https_session;
			https_session = nullptr;
			return 1;
		}
			
           //等待响应结果
		std::ostringstream responseStream;
		Poco::StreamCopier::copyStream(streamIn, responseStream);
		std::string resultStr = responseStream.str();

		delete https_session;
		https_session = nullptr;
		//解析JSON响应结果
		Poco::JSON::Parser parser;
		auto root = parser.parse(resultStr);
		Poco::JSON::Object::Ptr objRoot = root.extract<Poco::JSON::Object::Ptr>();
		
		int codeResult = objRoot->getValue<int>("code");
		if(codeResult == 200)
		{
                  return 0;
		}
		return codeResult;
	}
	catch (Poco::Exception& e)
	{
      //处理异常
	}
}

4.下载文件

int downloadFileFromUrl(std::string url_path)
{
    Poco::URI uri(url_path);
    //定义客户端
    Poco::Net::HTTPClientSession* http_session = 
    new HTTPClientSession();
    http_session->setPort(uri.getPort());
    http_session->setHost(uri.getHost());
    
    //发送请求获取响应
    Poco::Net::HTTPRequest request(
	Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(),
	Poco::Net::HTTPMessage::HTTP_1_1);
    Poco::Net::HTTPResponse response;
    https_session->sendRequest(request);
    std::istream &streamIn = https_session->receiveResponse(response);
    if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK)
    {
	    //先下载到对应的临时文件
        //先下载到临时文件再校验完整性之后再去替换对应的文件
     }
}

使用HTTPS客户端

Poco::Net::HTTPSClientSession* GetHttpsClientSession()
{
    //获取本地证书
	std::string certificate_path = getCertificatePath();
    //初始化证书信息
	SSLManager::InvalidCertificateHandlerPtr handlerPtr(new AcceptCertificateHandler(false));
	Context::Ptr context = new Context(Context::TLSV1_2_CLIENT_USE, certificate_path, Poco::Net::Context::VERIFY_NONE, 9);
	SSLManager::instance().initializeClient(nullptr, handlerPtr, context);
	//生成https客户端
   HTTPSClientSession *session = new HTTPSClientSession(context);
   //设置超时时间
	session->setTimeout(5000 * 1000);
	return session;
}
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Poco C是一个流行的C++开发,可以帮助开发者快速构建高性能、可扩展的网络应用程序和服务。它提供了丰富的功能和工具,简化了开发过程,提高了开发效率。 Poco C有以下主要特点: 1. 网络和通信功能:Poco C提供了强大的网络和通信功能,包括HTTP、SMTP、FTP、DNS等协议的支持。开发者可以方便地创建和管理网络连接、发送和接收数据等操作。 2. 数据访问接口:Poco C提供了统一的数据访问接口,支持主流数据系统如MySQL、PostgreSQL、Oracle等。通过Poco C,开发者可以轻松进行数据操作,如查询、插入、更新等。 3. 多线程和并发:Poco C提供了强大的多线程和并发支持,可以帮助开发者设计和管理高效的多线程应用程序。它提供了线程、锁、条件变量等基本的多线程工具,并提供了各种高级的并发机制,如任务管道、线程池等。 4. 输入输出和文件系统:Poco C提供了丰富的输入输出和文件系统功能,开发者可以通过Poco C轻松地进行文件操作、流操作、日志记录等。 5. 安全性和加密:Poco C提供了各种安全性和加密功能的支持,包括SSL/TLS、SHA、MD5等。它可以帮助开发者保护数据安全,防止信息泄露。 总之,Poco C是一个功能强大且易于使用的C++开发,为开发者提供了丰富的功能和工具,以加快应用程序的开发过程,同时提高应用程序的性能和稳定性。无论是开发网络应用还是系统程序,Poco C都是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码农飞飞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值