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()方法的名称所暗示的那样,它启动了一个旨在将一定数量的数据从缓冲区写入套接字的操作。此方法保证在不发生错误的情况下,在相应的异步操作期间至少写入一个字节。这意味着,在一般情况下,为了将缓冲区中所有可用的数据写入套接字,我们可能需要多次执行此异步操作。

异步的调用此方法的步骤如下:

  1. 定义一个数据结构,其中包含一个指向套接字对象的指针、一个缓冲区和一个用作写入字节计数器的变量。
  2. 定义一个回调函数,该函数将在异步写入操作完成时调用。
  3. 在客户机应用程序中,分配并打开活动TCP套接字,并将其连接到远程应用程序。在服务器应用程序中,通过接受连接请求获得已连接的活动TCP套接字。
  4. 分配一个缓冲区,并用要写入套接字的数据填充它。
  5. 通过调用套接字的async_write_some()方法启动异步写入操作。指定步骤2中定义的函数作为回调函数。
  6. 在asio::io_service类的对象上调用run()方法。
  7. 在回调函数中,增加写入的字节计数器。如果写入的字节数小于需要写入的总字节数,则启动一个新的异步写操作来写入数据的下一部分。
#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

posted @   yyyyyllll  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示