Poco::Net提供了很多便利的开发组件。尽管Poco目前还不是一个很完美的C++类库,但是它从设计上和使用的简易程度上都有着较为超前的理念。
大概是去年年底,我开始使用Poco::Net封装的网络通信库取代了boost::asio,直至现在Poco的文档也并不多,不过使用方法很有套路性。Poco封装的组件可以说已经把开发者绑死在了这种固定的使用模式上,因此可以很轻易地搭建一个TCPServer并且跑起来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| struct ServiceApplicationParams { std::string listen_address; int max_queued; int max_threads; };
class ServiceApplication : public Poco::Util::ServerApplication { public: ServiceApplication(const std::string& serviceName, MessageDispatcher* messageDispatcher); virtual ~ServiceApplication();
public: int run(int argc, char** argv, Venus::ServiceApplicationParams* params); int main(const std::vector<std::string>& args); virtual void defineOptions(Poco::Util::OptionSet& options); virtual void handleOption(const std::string& name, const std::string& value);
private: void initialize(Poco::Util::Application& self); void uninitialize();
private: Venus::ServiceApplicationParams* _applicationParams; Poco::Net::SocketReactor _reactor; MessageQueue _messageQueue; std::string _serviceName; };
|
写过服务器应用的都知道,相比起使用平台自带的Native Socket Api而言,上面的代码充满了现代C++感,可读性很好。首先我们把服务进程抽象为一个Application,这也是由继承Poco::Util::ServerApplication开始的。它提供了run()方法作为启动入口。根据这种设计,我们也可以把服务编译为动态库,以组件的形式提供给service box,从外部启动。
要启用一个TCPServer也相当简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| Poco::Net::SocketAddress listenAddress(_applicationParams->listen_address); Poco::Net::ServerSocket socket(listenAddress); Poco::Net::TCPServerParams* serverParams = new Poco::Net::TCPServerParams(); serverParams->setMaxQueued(_applicationParams->max_queued); serverParams->setMaxThreads(_applicationParams->max_threads);
MessageQueueWorker queueWorker(_messageQueue); Poco::ThreadPool::defaultPool().start(queueWorker);
ConnectionFactory connectionFactory; connectionFactory.setMessageQueue(_messageQueue);
Poco::Net::TCPServer server(&connectionFactory, socket, serverParams); server.start(); info_log("Server started."); Poco::Util::ServerApplication::waitForTerminationRequest();
_messageQueue.wakeUpAll(); server.stop();
|
和传统做法一样,我们需要提供一个监听端口以及Socket. 与传统做法不一样的是,Poco给我们提供了一个Reactor,基于事件驱动。每当有新的连接产生时,便会从ConnectionFactory中创建一个Poco::Net::TCPServerConnection的实例。之后的工作,就交给消息队列处理,至于回调到上层的工作,自然也是通过消息队列分发出去。
Poco的代码易读易懂,但在这段时间的使用中,仍然遇到了Poco的不少小坑,包括Poco::Net和Poco::Data,存在一些不完美的设计缺陷。相信这些问题以后会得到很好的解决。
以上代码摘自Venus:https://github.com/AngryPowman/Coeus/tree/master/src/coeus/venus_net