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

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

时间2025-04-30 08:33:42分类IT科技浏览6953
导读:原文地址: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
网站跳出率高应该如何解决(什么叫网站跳出率) win10系统桌面移动不了图标(系统升级为WIN10后,为什么桌面图标无法移动?)