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