原文:http://blog.csdn.net/liuchangyu23/article/details/4398906
最近正在开发一个网络打印服务器程序,使用Boost::asio库来实现服务端。下面详细介子绍asio库的使用方法,仅用来总结学习经验。如有不对的地方请大家指正.废话少说,直接进入主题。
对于一个网络程序的服务器端我们需要提供的是服务器的address,和服务开放的端口号port。
在asio库中首先我们必须使用一个io_service类来支持所有的IO功能。需要注意到是我们必须调用io_service_my.run()函数来开启IO服务的事件循环以使功能都能被正常使用。
boost::asio::io_service io_service_my;
现在我们可以基于这个io_service_my来关联构建一下几个类:
1. boost::asio::ip::tcp::acceptor acceptor_my(io_service_my);
因为LPD的实现是基于TCP传输协议,所以也使用了TCP的acceptor来接收client发来的连接。
2. boost::asio::ip::tcp::resolver resolver_my(io_service_my);
boost::asio::ip::tcp::resolver::query query_my(address,port);
boost::asio::ip::tcp::endpoint endpoint_my = *resolver.resolve(query_my);
这几个类主要是用来实现对地址的解析和绑定终端节点到相应的开放端口号上。首先构造一个关联到io_service_my的解析器resolver_my。然后让解析器resolver_my执行resolve
()函数来解析query_my指定的address和port到一个终端节点endpoint_my上。我们会看到这个endpoint_my终端节点会被绑定到这个acceptor_my接收器上。
3. boost::asio::ip::tcp::socket socket_my(io_service_my);
定义一个基于TCP协议的socket关联到io_service_my对象上。
在这些准备工作做完后我们开始一些实际的动作:
/*
* 打开一个使用由endpoint_my指定的协议类型的接收器,这个protocol()函数会自动返回与endpoint_my关联的协
* 议类型。
*/
acceptor_my.open(endpoint_my.protocol());
/*
* 设置选项允许socket绑定到一个已经正在被使用的地址。
*/
acceptor_my.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true);
/*
* 把接收器绑定到已经被设置过的endpoint_my。
*/
acceptor_my.bind(endpoint_my);
/*
* 接收器开始侦听。
*/
acceptor_my.listen();
/*
* 以同步/异步方式开始接收连接。
*/
acceptor_my.accept(socket_my) //同步
acceptor_my.async_accept(socket_my,
boost::bind(&handle_accept,boost::asio::placeholders::error));//异步
其中异步的侦听函数原型是:
template<
typename SocketService,
typename AcceptHandler>
void async_accept(
basic_socket< protocol_type, SocketService > & peer,
AcceptHandler handler);
handler所对应的函数在新连接接收完成后会被调用。这种异步方式实现回调的方法也类似于使用boost::asio::io_service::post(boost::bind(&handle_accept));
注意到bind函数中的&handle_accept,这是函数handle_accept的入口地址,也就是在接收完成后会调用的函数在这里我们可以继续进行下一步的处理,从socket_my中读取或者写
入数据。
/*
* 调用异步读函数,把接收的数据拷贝到buffer缓存中,其中buffer是由参数buffer_my构造,
* 而buffer_my本身可以是一个容器例如boost::array<char,8192> buffer_my,表示申请了
* 一个8K个char字符型空间。也可以使用例外一种方法实现buffer的构造例如
* boost::asio::buffer(data,size_t);其中data表示指向某种数据类型的指针,
* size_t则表示包含多少个该数据类型的元素。
*/
void handle_accept(boost::system::error_code error)
{
if(!error)
{
boost::array<char, 8192> buffer_my;
boost::asio::async_read(socket_my, boost::asio::buffer(buffer_my),
boost::bind(&handle_read, boost::asio::placeholders::error));
}
}
类似的写程序如下
boost::asio::async_write(socket_my, boost::asio::buffer(buffer_my),
boost::bind(&handle_write,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
最后在所有连接完成之后或是服务器停止的时候别忘记关掉连接。例如
socket_my.close();
acceptor_my.close();
至此一个基于boost::asio库的网络程序的框架就出来了,至于具体的设计类实现可以视需求而定。