【boost学习】之boost::asio(3)——socket编程
2014-10-26 17:57
369 查看
asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程。
一、同步服务器版本
客户端
客户端的代码如下:
主要流程如下:
(1)通过tcp::socket类定义一个tcp client对象socket
(2)通过connect函数连接服务器,打开socket连接。
(3)通过read_some函数来读数据
另外,还可以通过write_some来写数据,通过close来关闭socket连接(这里是通过释放socket对象隐式释放连接)。
服务器
服务器代码如下:
主要流程如下:
(1)通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)
(2)通过accept函数获取远端连接
(3)通过远端连接的write_some函数将数据发往客户端
二、异步服务器
前面的服务器是同步版本,在大并发的场景下一般需要用到异步socket。服务器的异步版本如下:
这个异步版本的逻辑倒不是很复杂,基本上和.net中传统的异步socket相似,不过需要注意的是,由于c++中内存需要自己管理,而asio框架也没有提供任何管理机制,因此需要注意async_accept、async_send等函数的参数生命周期,切记不能在里面传入栈变量的引用。如果是堆变量,需要确保释放,本例中我是通过share_ptr来实现的自动释放。
更多的示例请参看asio官方文档。
【参考资料:
http://www.cnblogs.com/TianFang/archive/2013/02/02/2890529.html
关于匿名函数,参见:http://blog.csdn.net/augusdi/article/details/11773943
】
一、同步服务器版本
客户端
客户端的代码如下:
//code of client #include <iostream> #include <boost/array.hpp> #include <boost/asio.hpp> using namespace std; using boost::asio::ip::tcp; int main(int argc, char* argv[]) { try { //(1)通过tcp::socket类定义一个tcp client对象socket boost::asio::io_service io; tcp::socket socket(io); //(2)通过connect函数连接服务器,打开socket连接。 tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 3200); socket.connect(end_point); for (;;) { boost::array<char, 128> buf; boost::system::error_code error; //(3)通过read_some函数来读数据 size_t len = socket.read_some(boost::asio::buffer(buf), error); if (error == boost::asio::error::eof) { break; //connection closed cleadly by peer } else if (error) { throw boost::system::system_error(error); //some other error } cout.write(buf.data(), len); } } catch (std::exception& e) { cout<<e.what()<<endl; } }
主要流程如下:
(1)通过tcp::socket类定义一个tcp client对象socket
(2)通过connect函数连接服务器,打开socket连接。
(3)通过read_some函数来读数据
另外,还可以通过write_some来写数据,通过close来关闭socket连接(这里是通过释放socket对象隐式释放连接)。
服务器
服务器代码如下:
//code of server #include <ctime> #include <iostream> #include <string> #include <boost/asio.hpp> using namespace std; using namespace boost; using boost::asio::ip::tcp; int main(int argc, char*argv[]) { try { //(1)通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定) asio::io_service io; tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 3200)); for (;;) { //(2)通过accept函数获取远端连接 tcp::socket socket(io); acceptor.accept(socket); time_t now = time(0); string message = ctime(&now); //(3)通过远端连接的write_some函数将数据发往客户端 system::error_code ignored_error; socket.write_some(asio::buffer(message), ignored_error); } } catch (std::exception &e) { cout<<e.what()<<endl; } }
主要流程如下:
(1)通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)
(2)通过accept函数获取远端连接
(3)通过远端连接的write_some函数将数据发往客户端
二、异步服务器
前面的服务器是同步版本,在大并发的场景下一般需要用到异步socket。服务器的异步版本如下:
//code of asyc server #include <ctime> #include <iostream> #include <string> #include <memory> #include <functional> #include <boost/asio.hpp> using boost::asio::ip::tcp; using namespace std; void process_socket(shared_ptr<tcp::socket> socket) { time_t now = time(0); shared_ptr<string> message(new string(ctime(&now))); auto callback = [=](const boost::system::error_code& err, size_t size) //匿名函数:用到的任何外部变量都隐式按值捕获 { if ((int)size == message->length()) { cout<<"Write completed"<<endl; } }; //(3)通过远端连接的write_some函数将数据发往客户端 socket->async_send(boost::asio::buffer((*message)), callback); } typedef function<void (const boost::system::error_code&)> accept_callback; void start_accept(tcp::acceptor& acceptor) { shared_ptr<tcp::socket> socket(new tcp::socket(acceptor.get_io_service())); accept_callback callback = [&acceptor, socket](const boost::system::error_code& error)//匿名函数:socket按值捕获, acceptor按引用捕获 { if (!error) { process_socket(socket); } //循环:相当于同步服务器中的for循环 start_accept(acceptor); }; //(2)通过accept函数获取远端连接 acceptor.async_accept(*socket, callback); } int main() { try { //(1)通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定) boost::asio::io_service io; tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 3200)); start_accept(acceptor); //异步必须要主动调用io_service::run io.run(); } catch (std::exception& e) { cout<<e.what()<<endl; } }
这个异步版本的逻辑倒不是很复杂,基本上和.net中传统的异步socket相似,不过需要注意的是,由于c++中内存需要自己管理,而asio框架也没有提供任何管理机制,因此需要注意async_accept、async_send等函数的参数生命周期,切记不能在里面传入栈变量的引用。如果是堆变量,需要确保释放,本例中我是通过share_ptr来实现的自动释放。
更多的示例请参看asio官方文档。
【参考资料:
http://www.cnblogs.com/TianFang/archive/2013/02/02/2890529.html
关于匿名函数,参见:http://blog.csdn.net/augusdi/article/details/11773943
】
相关文章推荐
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- boost.asio系列——socket编程
- 【boost】boost::asio(3)——socket编程
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- boost.asio系列——socket编程
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- 【兴趣爱好】之:Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio,libevent和ACE之间关于Socket编程的比较(★firecat推荐★)
- boost-asio学习2——同步、异步socket处理
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost asio学习笔记之二—— 网络编程
- boost.asio系列——socket编程
- Boost.Asio和ACE之间关于Socket编程的比较
- Boost.Asio和ACE之间关于Socket编程的比较