设为首页 加入收藏

TOP

Boost.Asio c++ 网络编程翻译(14)(一)
2015-07-20 17:29:05 来源: 作者: 【 】 浏览:6
Tags:Boost.Asio 网络编程 翻译
保持活动 假如,你需要做下面的操作: io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, buffer(buff)); 在这个例子中,sock和buff的存在时间都必须比read()调用的时间要长。也就是说,在调用read()返回之前,它们都必须有效。这就是你期望的;你传给一个方法的所有参数在参数内部都必须有效。当我们采用异步方式时,事情会变得越复杂。 io_service service; ip::tcp::socket sock(service); char buff[512]; void on_read(const boost::system::error_code &, size_t) {} ... async_read(sock, buffer(buff), on_read); 在这个例子中,sock和buff的存在时间都必须比read()操作本身时间要长,但是read操作的时间我们是不知道的,因为它是异步的。 当使用socket缓冲区的时候,你会有一个buffer实例在异步调用时一直存在(使用boost::shared_array<>)。在这里,我们可以使用同样的方式,通过创建一个类并在其内部管理socket和它的读写缓冲区。然后,对于所有的异步操作,我会传递一个包含智能指针的boost::bind仿函数:
using namespace boost::asio;
   io_service service;
   struct connection : boost::enable_shared_from_this
  
    {

  
       typedef boost::system::error_code error_code;
       typedef boost::shared_ptr
  
    ptr;
       connection() : sock_(service), started_(true) {}
       void start(ip::tcp::endpoint ep) {

  
           sock_.async_connect(ep,
                 boost::bind(&connection::on_connect, shared_from_this(),

_1)); }

       void stop() {
           if ( !started_) return;
           started_ = false;
           sock_.close();

}

       bool started() { return started_; }
   private:
       void on_connect(const error_code & err) {
           // here you decide what to do with the connection: read or
   write
           if ( !err)      do_read();
           else            stop();
       }
       void on_read(const error_code & err, size_t bytes) {
           if ( !started() ) return;
           std::string msg(read_buffer_, bytes);
page64image11240
if ( msg == "can_login")
else if ( msg.find("data ") == 0)
else if ( msg == "login_fail")
do_write("access_data");
process_data(msg);
stop();
}
void on_write(const error_code & err, size_t bytes) {

do_read(); }

void do_read() {
           sock_.async_read_some(buffer(read_buffer_),
                 boost::bind(&connection::on_read, shared_from_this(),

_1, _2)); }

       void do_write(const std::string & msg) {
           if ( !started() ) return;
           // note: in case you want to send several messages before
           //       doing another async_read, you'll need several write
   buffers!
           std::copy(msg.begin(), msg.end(), write_buffer_);
           sock_.async_write_some(buffer(write_buffer_, msg.size()),
                 boost::bind(&connection::on_write, shared_from_this(),

_1, _2)); }

       void process_data(const std::string & msg) {
           // process what comes from server, and then perform another

write }

   private:
       ip::tcp::socket sock_;
       enum { max_msg = 1024 };
       char read_buffer_[max_msg];
       char write_buffer_[max_msg];
       bool started_;

};

   int main(int argc, char* argv[]) {
       ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"),
   8001);
       connection::ptr(new connection)->start(ep);

}

在所有异步调用中,我们传递一个boost::bind仿函数当作参数。这个仿函数内部包含了一个智能指针,指向connection实例。只要有一个异步操作等待时,Boost.Asio会保存boost::bind仿函数的拷贝,这个拷贝保存了指向连接实例的一个智能指针,从而保证connection实例保持活动。问题解决!

当然,connection类仅仅是一个skeleton类;你需要根据你的需求对它进行调整(它看起来会和服务端的情况相当不同)。

你需要注意创建一个新的连接是相当简单的:connection::ptr(new connection)- >start(ep)。这个方法启动了到服务端的(异步)连接。当你需要关闭这个连接时,调用stop()。

当实例被启动时(start()),它将会等待被连接。当连接发生时。on_connect()被调用。如果没有错误发生,它启动一个read操作(do_read())。当read操作结束时,你解析这个消息;你应用的on_read()看起来会各种各样。当你写回一个消息时,你需要把它拷贝到缓冲区,然后像我在do_write()方法中所做的一样将其发送出去,因为再一次,这个缓冲区需要在这个异步写操作中一直存活。最后需要注意的一点――当写回时,你需要指定写入的数量,否则,整个缓冲区都会被发送出去。

总结

网络api实际上要大得多,这个章节只是一个参考,当你在实现你自己的网络应用时,你需要回来查看。

Boost.Asio实现了端点的概念,你可以认为是IP和端口。如果你不知道准确的IP,你可以使用resolver对象将主机名,例如www.yahoo.com转换为一个或多个I

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇HDU 4802-GPA(水) 下一篇POJ3061 Subsequence(二分前缀和..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·About - Redis (2025-12-26 08:20:56)
·Redis: A Comprehens (2025-12-26 08:20:53)
·Redis - The Real-ti (2025-12-26 08:20:50)
·Bash 脚本教程——Li (2025-12-26 07:53:35)
·实战篇!Linux shell (2025-12-26 07:53:32)