一、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>());