今天让我们来开始一个简单的HTTP程序,分为客户端和服务器。
先来完成一个客户端程序。所要关心的类有
HTTPSClientSession //HTTP会话类
HTTPRequest //HTTP请求类
HTTPResponse //HTTP回应类
首先当然是建立一个会话,在此基础上发送一个请求,最后收到一个回应。
HTTPClientSession s("127.0.0.1",9090); //指定目标的IP地址和端口
HTTPRequest request(HTTPRequest::HTTP_POST); //指定请求的类型,这个类的构造函数还有其他默认参数,例如第二个默认的是目标在服务的路劲,第三个是 HTTP消息的版本
request.setContentType("application/x-www-form-urlencoded\r\n");//设置HTTP消息的内容编码类型
std::string body = ""; //你要发送的数据体
request.setContentLength( (int)body.length() ); //长度
std::ostream& send = s.sendRequest(request); //sendRequest(...)返回一个输出流的引用,用法见下句
send << body <<std::flush; //将数据体从这个流发送出去
char buffer[1024] = {0}; //定义一个接受数组
HTTPResponse response; //定义一个回应类对象
std::istream& res = s.receiveResponse(response); //receiveResponse(...)返回一个输入流的引用,用法见下句
res.read(buffer,1024); //读,输入
std::cout<<buffer<<std::endl; //输出结果
这是一个非常简单的小例子,在工程中,它可能作为一个循环的主体,执行很多遍,所以可以把
HTTPClientSession
声明为成员,在每次发送,接受后,调用HTTPClientSession::reset();重置会话,关闭套接字,等待下个会话到来。
再来看一下服务器端。所要关系的类有
ServerApplication //服务器应用程序
MyRequestHandlerFactory //请求处理生成工厂
MyRequestHandler //具体的请求处理
在服务器程序里面生成一个工厂,每当一个request到来,工厂对其进行辨别处理,类似于switch语句,每一个case就对应一个具体处理。
class MyRequestHandler : public HTTPRequestHandler
{
public:
virtual void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
{
resp.setStatus(HTTPResponse::HTTP_OK);
resp.setContentType("application/x-www-form-urlencoded\r\n");
ostream& out = resp.send(); //返回一个回复的流引用
out << "<h1>Hello world!</h1>"<<"\r\n\r\n"
<< "<p>Count: " << ++count << "</p>"<<"\r\n\r\n"
<< "<p>Host: " << req.getHost() << "</p>"<<"\r\n\r\n"
<< "<p>Method: " << req.getMethod() << "</p>"<<"\r\n\r\n"
<< "<p>URI: " << req.getURI() << "</p>";
out.flush(); //将这个信息会送到客户端
}
private:
static int count;
};
int MyRequestHandler::count = 0;
class MyRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest &)
{
return new MyRequestHandler; //这个地方直接就对所有的请求授以相同的处理
}
};
class MyServerApp : public ServerApplication
{
protected:
int main(const vector<string> &) //run函数里面调用这个mian()函数
{
HTTPServer s(new MyRequestHandlerFactory, ServerSocket(9090), new HTTPServerParams);//创建一个具有多线程特性的服务器类,其实这个类才是这个程序 的核心,它接受参数“工厂”,以及制定服务器端口
s.start();
cout << endl << "Server started" << endl;
waitForTerminationRequest(); //等待用户点击关闭按钮,此时一直运行着,阻塞在此
cout << endl << "Shutting down..." << endl;
s.stop();
return Application::EXIT_OK;
}
};
int main(int argc, char** argv)
{
MyServerApp app;
return app.run(argc, argv); //让服务器运行起来
}
程序完毕了,我想感叹,POCO库不咋的,突如其来的异常,晦涩的语法,匮乏的文档,简陋的辅助,糟糕,本程序还只是普通的HTTP,接下来的HTTPS将会非常麻烦,我是这么认为的,等我有足够把握了,才敢写上下篇关于HTTPS的文章,再次感叹。
说起Qt,它的API可是优美啊。