BOOST::ASIO为我们提供了两种I/O机制,分别是同步和异步。它可在多平台上移植,在不同系统上采用了不同的实现。ASIO为我们封装了一系列的socket api,同时为我们提供了一套相当完善的服务器编程体系,部分概念(关键词)如:io队列、基于回调的异步通知、定时器、自定义的多线程机制。

假设大家已经安装好了boost,并有一些C++基础,针对TCP服务器编程,我们有如下需求:
1.一个可用于接受新连接的类
2.提供基本的send/recv io操作
3.解决多线程下的资源竞争问题
4.管理连接的生命周期
5.为不同的网络事件提供回调方法

针对以上需求,先来设计一个简单的框架。我们分为TCPServer, Acceptor, Connection三个主要的类。它们的功能分别如下:
TCPServer : 对用户可见,用于启动服务,终止服务。一个服务需要一个TCPServer对象。
Acceptor : 对用户不可见。用于监听并接受新的客户端连接。有新连接到来之后通知TCPServer,由TCPServer告知用户。
Connection : 对用户可见。封装了对客户端连接的一个实体,每个Connection对象表示与客户端的一个连接。由智能指针管理生命周期。

时序图如下:
uml_connect_sequence
如上图所示,客户端先发起一个连接,Acceptor会接受该连接,然后通过回调告知TCPServer,再由TCPServer通知用户(这里指TCPServer的上层使用者)有一个新的客户端接入了。那么,Acceptor应该通过什么方式去告知TCPServer,而用户又通过什么样的方式去获得这些通知呢?我们来画一个服务启动时的时序图:
uml_start_server_sequence

首先,User角色代表的也就是我们说的应用层用户,它先向TCPServer注册一些事件,而这些注册的事件,就是我们需要回调的方法。然后在启动Acceptor的时候,同时向Acceptor注册它所关心的事件,当Acceptor接受到新的连接时,它也会同时向新创建的Connection对象注册它所关心的事件。

这里所说的“注册事件”实质上是指设置一个函数指针。前段时间曾经在muduo的相关文章中看到陈硕提出了使用bind/functional方式来实现服务器网络事件的回调工作,我们不再需要和过去我们熟知的那种方式去继承某个类然后实现其接口,这种做法无疑会增加代码编写的灵活性,但他的文中同时提出的“继承是个坑”,我感觉这是一种比较情绪化的说法,不应该去拘泥哪种做法,个人建议根据具体场景去设计即可。

服务器的设计如上所述,下面将从ASIO的io_service说起,一步步去完善一个小型的服务端程序,并会逐一去解决需求中尚未实现的几条。


未完待续…