首页IT科技枚举实现接口(boost::asio::ip::tcp实现网络通信的小例子(转载) fengyc 博客园)

枚举实现接口(boost::asio::ip::tcp实现网络通信的小例子(转载) fengyc 博客园)

时间2025-08-04 20:53:38分类IT科技浏览8795
导读:原文地址:http://www.cppblog.com/janvy/archive/2010/03/24/110478.html 服务端: Boost.Asio是一个跨平台的网络及底层IO的C++编...

原文地址:http://www.cppblog.com/janvy/archive/2010/03/24/110478.html

服务端:

Boost.Asio是一个跨平台的网络及底层IO的C++编程库                  ,它使用现代C++手法实现了统一的异步调用模型                  。

头文件

#include <boost/asio.hpp>

名空间

using namespace boost::asio;

ASIO库能够使用TCP                  、UDP                           、ICMP          、串口来发送/接收数据                           ,下面先介绍TCP协议的读写操作

对于读写方式          ,ASIO支持同步和异步两种方式              ,首先登场的是同步方式                          ,下面请同步方式自我介绍一下:

大家好!我是同步方式!

我的主要特点就是执着!所有的操作都要完成或出错才会返回               ,不过偶的执着被大家称之为阻塞          ,实在是郁闷~~(场下一片嘘声)                          ,其实这样 也是有好处的                    ,比如逻辑清晰     ,编程比较容易                           。

在服务器端                          ,我会做个socket交给acceptor对象                        ,让它一直等客户端连进来,连上以后再通过这个socket与客户端通信                      , 而所有的通信都是以阻塞方式进行的                            ,读完或写完才会返回          。

在客户端也一样     ,这时我会拿着socket去连接服务器                  ,当然也是连上或出错了才返回                           ,最后也是以阻塞的方式和服务器通信              。

有人认为同步方式没有异步方式高效          ,其实这是片面的理解                          。在单线程的情况下可能确实如此              ,我不能利用耗时的网络操作这段时间做别的事 情                          ,不是好的统筹方法               。不过这个问题可以通过多线程来避免               ,比如在服务器端让其中一个线程负责等待客户端连接          ,连接进来后把socket交给另外的线程去 和客户端通信                          ,这样与一个客户端通信的同时也能接受其它客户端的连接                    ,主线程也完全被解放了出来          。

我的介绍就有这里     ,谢谢大家!

好                          ,感谢同步方式的自我介绍                        ,现在放出同步方式的演示代码(起立鼓掌!):

服务器端
#include<iostream> #include<boost/asio.hpp> usingnamespaceboost::asio; intmain(intargc,char*argv[]) { //所有asio类都需要io_service对象 io_serviceiosev; ip::tcp::acceptoracceptor(iosev, ip::tcp::endpoint(ip::tcp::v4(),1000)); for(;;) { //socket对象 ip::tcp::socketsocket(iosev); //等待直到客户端连接进来 acceptor.accept(socket); //显示连接进来的客户端 std::cout<<socket.remote_endpoint().address()<<std::endl; //向客户端发送helloworld! boost::system::error_codeec; socket.write_some(buffer("helloworld!"),ec); //如果出错,打印出错信息 if(ec) { std::cout<< boost::system::system_error(ec).what()<<std::endl; break; } //与当前客户交互完成后循环继续等待下一客户连接 } return0; }
客户端
#include<iostream> #include<boost/asio.hpp> usingnamespaceboost::asio; intmain(intargc,char*argv[]) { //所有asio类都需要io_service对象 io_serviceiosev; //socket对象 ip::tcp::socketsocket(iosev); //连接端点                      ,这里使用了本机连接                            ,可以修改IP地址测试远程连接 ip::tcp::endpointep(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; }

从演示代码可以得知

ASIO的TCP协议通过boost::asio::ip名 空间下的tcp类进行通信                          。 IP地址(address,address_v4,address_v6)              、 端口号和协议版本组成一个端点tcp:: endpoint)                    。用于在服务器端生成tcp::acceptor对 象                  ,并在指定端口上等待连接;或者在客户端连接到指定地址的服务器上     。 socket是 服务器与客户端通信的桥梁                           ,连接成功后所有的读写都是通过socket对 象实现的          ,当socket析 构后              ,连接自动断 开                          。 ASIO读写所用的缓冲区用buffer函 数生成                          ,这个函数生成的是一个ASIO内部使用的缓冲区类               ,它能把数组                          、指针(同时指定大 小)               、std::vector          、std::string                          、boost::array包装成缓冲区类                        。 ASIO中的函数                    、类方法都接受一个boost::system::error_code类 型的数据          ,用于提供出错码。它可以转换成bool测试是否出错                          ,并通过boost::system::system_error类 获得详细的出错信息                      。另外                    ,也可以不向ASIO的函数或方法提供 boost::system::error_code     ,这时如果出错的话就会直 接抛出异常                          ,异常类型就是boost::system:: system_error(它是从std::runtime_error继承的)                            。 另一个例子:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 我稍稍整理了下                        ,就是加了点注释,很基本的东西                      ,大家可以参考socket的几个流程                            ,我上面也有提示的     ,希望对大家有所帮助     。最后                  ,如果大家有什么好的方法希望能让我也分享下                           ,谢谢! #include<boost/asio.hpp>#include<boost/bind.hpp>#include<boost/shared_ptr.hpp>#include<boost/enable_shared_from_this.hpp>#include<iostream>usingboost::asio::ip::tcp;#definemax_len 1024

class

clientSession

:publicboost::enable_shared_from_this<clientSession>{public:clientSession(boost::asio::io_service&ioservice):m_socket(ioservice){memset(data_,\0,sizeof(data_));}~clientSession(){}tcp::socket&socket(){returnm_socket;}voidstart(){boost::asio::async_write(m_socket,boost::asio::buffer("link successed!"),boost::bind(&clientSession::handle_write,shared_from_this(),boost::asio::placeholders::error));

/*async_read跟客户端一样          ,还是不能进入handle_read函数,如果你能找到问题所在              ,请告诉我                          ,谢谢*/

// --已经解决               ,boost::asio::async_read(...)读取的字节长度不能大于数据流的长度          ,否则就会进入

// ioservice.run()线程等待                          ,read后面的就不执行了                  。

//boost::asio::async_read(m_socket,boost::asio::buffer(data_,max_len),

//boost::bind(&clientSession::handle_read,shared_from_this(),

//boost::asio::placeholders::error));

//max_len可以换成较小的数字                    ,就会发现async_read_some可以连续接收未收完的数据

m_socket.async_read_some(boost::asio::buffer(data_,max_len),boost::bind(&clientSession::handle_read,shared_from_this(),boost::asio::placeholders::error));}private:voidhandle_write(constboost::system::error_code&error){

if(error){m_socket.close();}

}voidhandle_read(constboost::system::error_code&error){

if(!error){std::cout<<data_<<std::endl;

//boost::asio::async_read(m_socket,boost::asio::buffer(data_,max_len),

//boost::bind(&clientSession::handle_read,shared_from_this(),

//boost::asio::placeholders::error));

m_socket.async_read_some(boost::asio::buffer(data_,max_len),boost::bind(&clientSession::handle_read,shared_from_this(),boost::asio::placeholders::error));}else{m_socket.close();}

}private:tcp::socketm_socket;chardata_[max_len];};

class

serverApp

{typedefboost::shared_ptr<clientSession>session_ptr;public:serverApp(boost::asio::io_service&ioservice,tcp::endpoint&endpoint):m_ioservice(ioservice),acceptor_(ioservice,endpoint){session_ptr new_session(newclientSession(ioservice));acceptor_.async_accept(new_session->socket(),boost::bind(&serverApp::handle_accept,this,boost::asio::placeholders::error,new_session));}~serverApp(){}private:voidhandle_accept(constboost::system::error_code&error,session_ptr&session){if(!error){std::cout<<"get a new client!"<<std::endl;

//实现对每个客户端的数据处理

session->start();

//在这就应该看出为什么要封session类了吧     ,每一个session就是一个客户端

session_ptr new_session(newclientSession(m_ioservice));acceptor_.async_accept(new_session->socket(),boost::bind(&serverApp::handle_accept,this,boost::asio::placeholders::error,new_session));}}private:boost::asio::io_service&m_ioservice;tcp::acceptor acceptor_;};

intmain(intargc,char*argv[]){boost::asio::io_service myIoService;shortport=8100/*argv[1]*/;

//我们用的是inet4

tcp::endpoint endPoint(tcp::v4(),port);

//终端(可以看作sockaddr_in)完成后                          ,就要accept了

serverApp sa(myIoService,endPoint);

//数据收发逻辑

myIoService.run();return0;}
声明:本站所有文章                        ,如无特殊说明或标注,均为本站原创发布                           。任何个人或组织                      ,在未征得本站同意时                            ,禁止复制     、盗用                          、采集                        、发布本站内容到任何网站、书籍等各类媒体平台          。如若本站内容侵犯了原著者的合法权益     ,可联系我们进行处理              。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
电脑充电一直是0%怎么办(笔记本电池怎么修复) php分页实现跳转(无刷新分页 jquery.pagination.js 张龙豪 博客园)