boost.asio系列——socket编程
asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程。
客户端
客户端的代码如下:
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
boost::asio::io_service io_service;
tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 3200);
tcp::socketsocket(io_service);
socket.connect(end_point);
for (;;)
{
boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
std::cout.write(buf.data(), len);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
主要流程如下:
- 通过tcp::socket类定义一个tcp client对象socket
- 通过connect函数连接服务器,打开socket连接。
- 通过read_some函数来读数据
另外,还可以通过write_some来写数据,通过close来关闭socket连接(这里是通过释放socket对象隐式释放连接)。
服务器
服务器代码如下:
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
using namespace boost;
using boost::asio::ip::tcp;
int main()
{
try
{
asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));
for (;;)
{
tcp::socket socket(io_service);
acceptor.accept(socket);
time_t now = time(0);
std::string message = ctime(&now);
system::error_code ignored_error;
socket.write_some(asio::buffer(message), ignored_error);
}
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
主要流程如下:
- 通过tcp::acceptor类创建一个tcp server对象,并绑定端口(也可以不在构造器中自动绑定,而通过bind函数手动绑定)
- 通过accept函数获取远端连接
- 通过远端连接的write_some函数将数据发往客户端
异步服务器
前面的服务器是同步版本,在大并发的场景下一般需要用到异步socket。服务器的异步版本如下:
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
void process_client(shared_ptr<tcp::socket> client)
{
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;
};
client->async_send(boost::asio::buffer(*message), callback);
}
typedef function<void (const boost::system::error_code&)> accept_callback;
void start_accept(tcp::acceptor& server)
{
shared_ptr<tcp::socket> client(new tcp::socket(server.get_io_service()));
accept_callback callback = [&server, client](const boost::system::error_code& error)
{
if (!error)
process_client(client);
start_accept(server);
};
server.async_accept(*client, callback);
}
int main()
{
try
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3200));
start_accept(acceptor);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
这个异步版本的逻辑倒不是很复杂,基本上和.net中传统的异步socket相似,不过需要注意的是,由于c++中内存需要自己管理,而asio框架也没有提供任何管理机制,因此需要注意async_accept、async_send等函数的参数生命周期,切记不能在里面传入栈变量的引用。如果是堆变量,需要确保释放,本例中我是通过share_ptr来实现的自动释放。
更多的示例请参看asio官方文档。
FROM:http://www.cnblogs.com/TianFang/archive/2013/02/02/2890529.html
boost.asio系列——socket编程的更多相关文章
- Boost.Asio c++ 网络编程翻译(20)
异步服务端 这个图表是相当复杂的:从Boost.Asio出来你能够看到4个箭头指向on_accept.on_read,on_write和on_check_ping. 着也就意味着你永远不知道哪个异步调 ...
- Boost.Asio c++ 网络编程翻译(14)
保持活动 假如,你须要做以下的操作: io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, ...
- Boost.Asio c++ 网络编程翻译(26)
Boost.Asio-其他特性 这章我们讲了解一些Boost.Asio不那么为人所知的特性.标准的stream和streambuf对象有时候会更难用一些,但正如你所见.它们也有它们的益处.最后,你会看 ...
- Boost.Asio c++ 网络编程翻译(21)
同步VS异步 Boost.Asio的作者做了一个非常惊艳的工作:它能够让你在同步和异步中自由选择,从而更好的适应你的应用. 在之前的章节中,我们学习了每种类型应用的框架,比方同步client,同步服务 ...
- Boost.Asio c++ 网络编程翻译(11)
*_at方法 这些方法在一个流上面做随机存取操作.你来指定read和write操作从什么地方開始(offset): async_read_at(stream, offset, buffer [, co ...
- boost.asio系列——io_service
IO模型 io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象). asio::io_service i ...
- boost boost::asio::read socket.read_some 区别
boost boost::asio::read 尝试读一定数量的字节,直到读到为止,或者出错 socket.read_some 读一下socket,读到多少算多少 带async的类似
- Boost.Asio c++ 网络编程翻译(16)
TCP异步服务端 核心功能和同步服务端的功能类似,例如以下: class talk_to_client : public boost::enable_shared_from_this<talk_ ...
- Boost.Asio c++ 网络编程翻译(10)
read/write方法 这些方法对一个流进行读写操作(能够是套接字,或者其它表现的像流的类): async_read(stream, buffer [, completion],handler):这 ...
随机推荐
- BufferedInputStream 源码分析
一.简介 BufferedInputStream会缓存一部分数据(默认8K),这个函数的作用就是读取更多的数据到缓存,必要的时候会扩大缓存的内容. 在该类中有几个重要的标志位:markpos,pos, ...
- Tcl语言笔记之二
1,表达式 1.1 操作数 TCL表达式的操作数通常是整数或实数.整数一般是十进制的, 但如果整数的第一个字符是0(zero),那么TCL将把这个整数看作八进制的,如果前两个字符是0x则这个整数被看作 ...
- MapReduce调度与执行原理之任务调度(续)
前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...
- hdu 1395 2^x mod n = 1 (简单数论)
题目大意: 求出一个最小的x 使得 2的x次方对n取模为1 思路分析: 若要 a*b%p=1 要使得b存在 则 gcd (a,p)=1. 那么我们应用到这个题目上来. 当n为偶数 2^x 也是偶数, ...
- CSS - 解决使用浮动,父窗体不能撑高问题
浮动的父级元素一定要用 clear 清除浮动,否则高度会无法撑开.
- scanf()常犯错误
------------------------------------------------------------------------ <> 本意:接收字符串. 写成代码:voi ...
- Oracle时间戳
查询某一具体时间某张表的数据,可以用时间戳进行查询. 例如: SELECT * FROM sac14 AS OF TIMESTAMP to_date('201508310930','yyyymmddh ...
- linux下利用sed重命名文件
3 for file in `ls ./*.*` 4 do 5 mv $file `echo $file|sed 's/IM_21R_ID331/1M21R_ID331/g'` 6 done ...
- 基于Zlib算法的流压缩、字符串压缩源码
原文:基于Zlib算法的流压缩.字符串压缩源码 Zlib.net官方源码demo中提供了压缩文件的源码算法.处于项目研发的需要,我需要对内存流进行压缩,由于zlib.net并无相关文字帮助只能自己看源 ...
- Swift - 使用NSURLSession同步获取数据(通过添加信号量)
过去通过 NSURLConnection.sendSynchronousRequest() 方法能同步请求数据.从iOS9起,苹果建议废除 NSURLConnection,使用 NSURLSessio ...