POCO C++ 框架 ---- http服务端

一、http服务端

POCO C++这个库服务端有一个很好的框架,在第一次接触确实比较难去切入,我这里讲解一下HTTPTimeServer这个官方例程.

这里我们直接看 HTTPTimeServer 类内的main函数,服务端的启动从这里开始。

config().getInt函数是从HTTPTimeServer.properties文件内容中获取参数的。

HTTPServerParams是线程池的参数设置,最大队列长度和最大线程数都在这里设置。

ServerSocket svs(port)这里创建服务端socket监听 端口为port的套接字。

HTTPServer srv(new TimeRequestHandlerFactory(format), svs, pParams); 实例化http服务端,

TimeRequestHandlerFactory(format)这里是请求处理工厂,每个合法请求在它内部创建一个请求处理实例

int main(const std::vector<std::string>& args)
	{
		if (false)
		{
			displayHelp();
		}
		else
		{
			// get parameters from configuration file
			unsigned short port = (unsigned short) config().getInt("HTTPTimeServer.port", 9943);
			std::string format(config().getString("HTTPTimeServer.format", DateTimeFormat::SORTABLE_FORMAT));
			int maxQueued  = config().getInt("HTTPTimeServer.maxQueued", 100);
			int maxThreads = config().getInt("HTTPTimeServer.maxThreads", 16);
			ThreadPool::defaultPool().addCapacity(maxThreads);

			HTTPServerParams* pParams = new HTTPServerParams;
			pParams->setMaxQueued(maxQueued);
			pParams->setMaxThreads(maxThreads);

			// set-up a server socket
			ServerSocket svs(port);
			// set-up a HTTPServer instance
			HTTPServer srv(new TimeRequestHandlerFactory(format), svs, pParams);
			// start the HTTPServer
			srv.start();
			ThreadPool::defaultPool().start(srv);
			Poco::ThreadPool::defaultPool().joinAll();
			
			// wait for CTRL-C or kill
            //这里会阻塞
			waitForTerminationRequest();
			// Stop the HTTPServer
			srv.stop();
		}
		return Application::EXIT_OK;
	}

      1.http服务端根据路径处理请求

这里每有一个请求成功发送到服务端时,都会经过这个函数,并创建对应的处理请求函数,在这里做请求路径判断,分发对应请求创建对应的类。注意种类需要继承 HTTPRequestHandlerFactory这个类才可以

HTTPRequestHandler* TimeRequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request)
{
	
	if (request.getURI() == "/")
	{
		return new TimeRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/checkPatentByCertificateNumber"))
	{
		return new CheckByCertificateNumberRequestHandler(_format);
	}	
	else if (std::string::npos != request.getURI().find("/UploadData"))
	{
		return new UploadDatabaseRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/DownloadDatabaseData"))
	{
		return new DownloadDatabaseRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/UploadFile"))
	{
		return new UploadFileRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/DownloadFile"))
	{
		return new DownloadFileRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/ShowFile"))
	{
		return new ShowFileRequestHandler(_format);
	}
	else if (std::string::npos != request.getURI().find("/DeletePatentInfo"))
	{
		return new DeleteByCertificateNumberRequestHandler(_format);
	}
	else
		return nullptr;
	
}

二、服务端获取请求内容并返回

1.返回时间html内容

        TimeRequestHandler类继承自HTTPRequestHandler,能拿到所有请求内容,并返回到服务端,这里是返回了一个当前时间.

class TimeRequestHandler: public HTTPRequestHandler
	/// Return a HTML document with the current date and time.
{
public:
	TimeRequestHandler(const std::string& format):
		_format(format)
	{
	}

	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
	{
		Application& app = Application::instance();
		//app.logger().information("Request from " + request.clientAddress().toString());

		Timestamp now;//当前时间
		std::string dt(DateTimeFormatter::format(now, _format));//_format前面获取的时间格式

		response.setChunkedTransferEncoding(true);
        //设置返回的内容类型。
		response.setContentType("text/html");
        //返回的响应码,类似200和404这种公共的,要返回自己定义的得设置自己构造json格式,
        response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
		std::ostream& ostr = response.send();
		ostr << "<html><head><title>HTTPTimeServer powered by POCO C++ Libraries</title>";
		ostr << "<meta http-equiv=\"refresh\" content=\"1\"></head>";
		ostr << "<body><p style=\"text-align: center; font-size: 48px;\">";
		ostr << dt;
		ostr << "</p></body></html>";
	}

private:
	std::string _format;
};

2.返回json内容

        Object 这里可以套娃,里面可以设置任意的数据,数组,键值等等

//构造一个json对象
Poco::JSON::Object object(Poco::JSON_PRESERVE_KEY_ORDER);
//设置键值
object.set("method", "UploadData");

//json转字符串
std::ostringstream ostr_stream;
object.stringify(ostr_stream);
//获取返回的流,并输入到里面去
std::ostream& out = response.send();
out << ostr_stream.str();

3.解析json数据

        3.1 解析字符串数据
        //创建解析器
		Parser sparser;
		// 解析 JSON 字符串 
		sparser.parse(strRequest);
		//获取结果
		Poco::DynamicAny json = sparser.result();

		//创建一个指针
		Poco::JSON::Object::Ptr obj;
        //判断是否为指针
		if (json.type() != typeid(Poco::JSON::Object::Ptr))
			return false;
        //结果赋值给obj
		obj = json.extract<Poco::JSON::Object::Ptr>();

		//获取键为CertificateNumber的值
		Var var = obj->get("CertificateNumber");
        if (var.type() != typeid(std::string))
		{
			strErro = "CertificateNumber is null";
			return false;
		}
        //这是std::string 如果直接赋值可能会出现异常
		stu.strCertificateNumber = var.toString();
  
3.2 解析整型数据和枚举
        //StartTime
		var = obj->get("StartTime");
		if (var.isInteger() || var.isNumeric())
		{
			strErro = "StartTime is null";
			return false;
		}
		stu.nStartTime = var.convert<time_t>();

        //PatentStatu
		var = obj->get("PatentStatu");
		if (var.isInteger() || var.isNumeric())
		{
			strErro = "PatentStatu is null";
			return false;
		}
        //枚举
		stu.ePatentStatu = static_cast<PatentStatus>(var.convert<uint8_t>());