03. I/O 操作(异步)
1.以异步的方式向TCP socket中写入
Boost.asio提供的用于异步将数据写入套接字的最基本工具是Asio::ip::tcp::socket类的async_write_some()方法。其中一个方法的重载:
template<typename ConstBufferSequence,typename WriteHandler> void async_write_some(const ConstBufferSequence & buffers,WriteHandler handler);
该方法启动写操作并立即返回。它接受一个对象,该对象表示一个缓冲区,其中包含要写入套接字的数据,作为其第一个参数。第二个参数是一个回调函数,该参数可以是函数指针、函子或满足WriteHandler概念要求的任何其他对象。
回调函数应该有以下签名:
void write_handler(const boost::system::error_code& ec,std::size_t bytes_transferred);
这里,ec是一个参数,如果发生错误代码,则指示错误代码,bytes_transfer_参数指示在相应的异步操作期间已向套接字写入了多少字节。
正如async_write_some()方法的名称所暗示的那样,它启动了一个旨在将一定数量的数据从缓冲区写入套接字的操作。此方法保证在不发生错误的情况下,在相应的异步操作期间至少写入一个字节。这意味着,在一般情况下,为了将缓冲区中所有可用的数据写入套接字,我们可能需要多次执行此异步操作。
异步的调用此方法的步骤如下:
- 定义一个数据结构,其中包含一个指向套接字对象的指针、一个缓冲区和一个用作写入字节计数器的变量。
- 定义一个回调函数,该函数将在异步写入操作完成时调用。
- 在客户机应用程序中,分配并打开活动TCP套接字,并将其连接到远程应用程序。在服务器应用程序中,通过接受连接请求获得已连接的活动TCP套接字。
- 分配一个缓冲区,并用要写入套接字的数据填充它。
- 通过调用套接字的async_write_some()方法启动异步写入操作。指定步骤2中定义的函数作为回调函数。
- 在asio::io_service类的对象上调用run()方法。
- 在回调函数中,增加写入的字节计数器。如果写入的字节数小于需要写入的总字节数,则启动一个新的异步写操作来写入数据的下一部分。
#include <boost/asio.hpp> #include <iostream> using namesapce boost; struct Session{ std::shared_ptr<asio::ip::tcp::socket> sock; std::string buf; std::size_t total_bytes_written; }//这个session类表示服务器端处理客户连接的管理类 void callback(const boost::system::error_code& ec, std::size_t bytes_transferred, std::shared_ptr<Session> s){ if(ec != 0){ std::cout<<"error occured! error code is"<<ec.value()<<".Message"<<ec.message(); return; } s->total_bytes_written += bytes_transferred; if(s->total_bytes_written == s->buf.length()){ return; } s->sock->async_write_some( asio::buffer( s->buf.c_str() + s->total_bytes_written, s->buf.length() - s->total_bytes_written), std::bind(callback, std::placeholders::_1, std::placeholders::_2, s)); } void writeToSocket(std::shared_ptr<asio::ip::tcp::socket> sock){ std::shared_ptr<Session> s(new Session); s->buf = std::string("hello"); s->total_bytes_written = 0; s->sock = sock; s->sock->async_write_some( asio::buffer(s->buf), std::bind(callback, std::placeholders::_1, std::placeholders::_2, s)); } int main(){ std::string raw_ip_address = "192.168.3.10"; unsigned short port_num = 3333; try{ asio::ip::tcp::endpoint ep(asio::ip::address::from_string(raw_ip_address),port_num); asio::io_context ioc; std::shared_ptr<asio::ip::tcp::socket> sock(new asio::ip::tcp::socket(ioc,ep.protocol())); sock->connect(ep); ioc.run(); }catch(system::system_error &e){ std::cout<<"error code = "<<e.code()<<".Message: "<<e.what(); return e.code().value(); } return 0; }
777
@@@ Do or Do Not, There is No Try! @@@
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义