boost asio 网络编程,boost asio socket
boost:asio:ip:tcp实现网络通信的小例子(转载)-fengyc-博客园
boost:asio:ip:tcp实现网络通信的一个小例子(转载)贴于2012-03-21 14:15 fengyc阅读(1289)评论(0)编辑收藏
原地址:http://www.cppblog.com/janvy/archive/2010/03/24/110478.html
服务器端:
助推。Asio是一个跨平台的网络和底层IO C编程库,它使用现代C技术来实现统一的异步调用模型。
头文件
#包含boost/asio.hpp命名空间
使用命名空间boost:asio;ASIO图书馆可以使用TCP、UDP、ICMP和串行端口发送/接收数据。这里首先介绍TCP协议的读写操作。
对于读写方法,ASIO支持同步和异步方法,其中第一种是同步方法。请介绍一下下面的同步方法:
大家好!我是同步的!
我的主要特点就是坚持!所有操作都要完成或者出错才会返回,而我的坚持却叫堵,真的很郁闷~ ~(场下嘘声)。其实这样也是有好处的,比如逻辑清晰,编程容易。
在服务器端,我会做一个socket给acceptor对象,让它等待客户端连接,然后通过这个socket和客户端通信。所有的交流都是以阻塞的方式进行的,只有读完或写完才会返回。
对于客户端来说也是如此。这时候,我会拿插座连接服务器。当然,我会在连接或出错后返回。最后,我会用阻塞的方式与服务器通信。
有人认为同步模式不如异步模式高效,但这其实是一种片面的理解。在单线程的情况下,这可能是正确的。我不能用耗时的网络操作去做其他事情,这不是一个好的统筹方法。但是,这个问题可以通过多线程来避免。比如在服务器端,其中一个线程负责等待客户端的连接,连接进来后将套接字交给另一个线程与客户端进行通信,这样在与一个客户端通信的同时可以接受其他客户端的连接,完全解放了主线程。
我的介绍到这里了,谢谢!
好了,感谢同步模式的自我介绍,现在放出同步模式的演示代码(起立鼓掌!):
server # includeiostrem # include boot/asio . hppusingnamespace boost:asio;Int (int argc,char * argv[]){//所有asio类都需要io_service对象io _ serviceiosevIP:TCP:acceptoracceptor(iosev,ip:tcp:endpoint(ip:tcp:v4(),1000));for(;){//socket对象IP:TCP:socket socket(iosev);//等待客户端连接到acceptor . accept(socket);//显示连接的客户端STD:cout socket . remote _ endpoint()。address()STD:endl;//向客户端发送helloworld!boost:system:error _ codeec;socket . write _ some(buffer( hello world!),EC);//如果有错误,打印错误信息If(EC){ STD:cout boost:system:system _ error(EC)。what()STD:endl;打破;}//与当前客户交互完成后,继续循环等待下一个客户连接} return0} client # includeiostrem # include boost/asio . hppusingnamespace boost:asio;Int (int argc,char * argv[]){//所有asio类都需要io_service对象io _ serviceiosev//socket对象IP:TCP:socket socket(iosev);//连接端点,这里使用本地连接。可以修改IP地址来测试远程连接IP: TCP:端点EP(IP:address _ v4:from _ string( 127 . 0 . 0 . 1 ),1000);//连接服务器boost:system:error _ codeec;socket.connect(ep,EC);//如果有错误,打印错误信息If(EC){ STD:cout boost:system:system _ error(EC)。what()STD:endl;return-1;}//接收数据charbuf[100];size _ tlen=socket . read _ some(buffer(buf),EC);std:cout.write(buf,len);return0}从演示代码中可以知道
音频流输入输出接口的三氯苯酚协议通过boost:asio:ip名空间下的传输控制协议类进行通信100 .互联网协议(Internet Protocol)地址(地址,地址_v4,地址_v6),端口号和协议版本组成一个端点(tcp:端点).用于在服务器端生成tcp:接受者对象,并在指定端口上等待连接;或者在客户端连接到指定地址的服务器上1000插座。是服务器与客户端通信的桥梁,连接成功后所有的读写都是通过窝对象实现的,当窝析构后,连接自动断开106 .音频流输入输出接口读写所用的缓冲区用缓冲器函数生成,这个函数生成的是一个音频流输入输出接口内部使用的缓冲区类,它能把数组、指针(同时指定大小)、std:vector、std:string、boost:数组包装成缓冲区类106 .音频流输入输出接口中的函数、类方法都接受一个升压:系统:错误代码类型的数据,用于提供出错码。它可以转换成弯曲件测试是否出错,并通过升压:系统:系统_错误类获得详细的出错信息。另外,也可以不向音频流输入输出接口的函数或方法提供boost:系统:错误代码这时如果出错的话就会直接抛出异常,异常类型就是升压:系统:系统错误(它是从标准:运行时错误继承的)。另一个例子::::::::我稍稍整理了下,就是加了点注释,很基本的东西,大家可以参考窝的几个流程,我上面也有提示的,希望对大家有所帮助。最后,如果大家有什么好的方法希望能让我也分享下,谢谢!
#包含boost/asio.hpp
#包含升压/绑定. hpp
#包含boost/shared_ptr.hpp
#包含boost/enable _ shared _ from _ thisHPP
#包括输入输出流
使用boost:asio:IP:TCP;
#definemax_len 1024
classclientSession
:public boost:enable _ shared _ from _ this客户端会话
{
公共:
客户端会话(boost:asio:io _ service io服务)
:m_socket(ioservice)
{
memset(data_, ,sizeof(data _));
}
~clientSession()
{}
tcp:套接字套接字()
{
returnm _ socket
}
voidstart()
{
boost:asio:异步写入(m_socket,
boost:asio:buffer(链接成功!),
boost:bind(客户端会话:handle _ write,shared_from_this(),
boost:asio:占位符:错误));
/*异步读取跟客户端一样,还是不能进入句柄_读取函数,如果你能找到问题所在,请告诉我,谢谢*///- 已经解决,boost:asio:async_read(.)读取的字节长度不能大于数据流的长度,否则就会进入
//ioservice.run()线程等待,阅读后面的就不执行了。
//boost:asio:async _ read(m _ socket,boost:asio:buffer(data_,max_len),
//boost:bind(客户端会话:handle _ read,shared_from_this(),
//boost:asio:placeholders:error));
//max_len可以换成较小的数字,就会发现异步_读取_一些可以连续接收未收完的数据
m _ socket。async _ read _ some(boost:asio:buffer(data _,max_len),
boost:bind(客户端会话:handle _ read,shared_from_this(),
boost:asio:占位符:错误));
}
私人:
void handle _ write(const boost:system:error _ code错误)
{
如果(错误)
{
m _ socket。close();
}
}
void handle _ read(const boost:system:error _ code error)
{
如果(!错误)
{
STD:cout data _ STD:endl;
//boost:asio:async _ read(m _ socket,boost:asio:buffer(data_,max_len),
//boost:bind(客户端会话:handle _ read,shared_from_this(),
//boost:asio:placeholders:error));
m _ socket。async _ read _ some(boost:asio:buffer(data _,max_len),
boost:bind(客户端会话:handle _ read,shared_from_this(),
boost:asio:占位符:错误));
}
其他
{
m _ socket。close();
}
}
私人:
TCP:socket TM _ socket;
chardata _[max _ len];
};
classserverApp
{
typedefboost:shared _ ptr客户端会话session _ ptr
公共:
服务器应用(boost:asio:io _ service io服务,tcp:endpoint端点)
:m_ioservice(ioservice),
acceptor_(ioservice,端点)
{
session _ ptr new _ session(新客户端会话(io服务));
接受者_。异步接受(新会话套接字(),
boost:bind(服务器app:handle _ accept,this,boost:asio:占位符:错误,
new _ session);
}
~serverApp()
{
}
私人:
void handle _ accept(const boost:system:error _ code error,session_ptr session)
{
如果(!错误)
{
获得一个新客户!STD:endl;
//实现对每个客户端的数据处理
会话开始();
//在这就应该看出为什么要封会议类了吧,每一个会议就是一个客户端
session _ ptr new _ session(新客户端会话(m _ io服务));
接受者_。异步接受(新会话套接字(),
boost:bind(服务器app:handle _ accept,this,boost:asio:占位符:错误,
new _ session);
}
}
私人:
boost:asio:io _ service m _ io服务;
TCP:acceptor acceptor _;
};
intmain(intargc,char*argv[])
{
boost:asio:io _ service myIoService;
短端口=8100/* argv[1]*/;
//我们用的是inet4
tcp:端点端点(tcp:v4(),端口);
//终端(可以看作sockaddr_in)完成后,就要接受了
serverApp sa(myIoService,endPoint);
//数据收发逻辑
myio服务。run();
返回0
}