Boost.Asio c++ 网络编程翻译(16)

TCP异步服务端

核心功能和同步服务端的功能类似,如下:

class talk_to_client : public boost::enable_shared_from_this<talk_to_
   client>
                        , boost::noncopyable {
       typedef talk_to_client self_type;
       talk_to_client() : sock_(service), started_(false) {}
   public:
       typedef boost::system::error_code error_code;
       typedef boost::shared_ptr<talk_to_client> ptr;
       void start() {
           started_ = true;

do_read(); }

       static ptr new_() {
           ptr new_(new talk_to_client);
           return new_;
       }
       void stop() {
           if ( !started_) return;
           started_ = false;
           sock_.close();
       }
       ip::tcp::socket & sock() { return sock_;}
       ...
   private:
       ip::tcp::socket sock_;
       enum { max_msg = 1024 };
       char read_buffer_[max_msg];
       char write_buffer_[max_msg];
       bool started_;

};

因为我们是非常简单的回显服务,这里不需要一个is_started()方法。对每个客户端,仅仅读取它的消息,回显,然后关闭它。

do_read(),do_write()和read_complete()方法和TCP同步服务端的完全一致。

主要的逻辑同样是在on_read()和on_write()方法中:

void on_read(const error_code & err, size_t bytes) {
       if ( !err) {
           std::string msg(read_buffer_, bytes);
           do_write(msg + "\n");
       }

stop(); }

   void on_write(const error_code & err, size_t bytes) {
       do_read();
}

对客户端的处理如下:

ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(),
   8001));
   void handle_accept(talk_to_client::ptr client, const error_code & err)
   {
       client->start();
       talk_to_client::ptr new_client = talk_to_client::new_();
       acceptor.async_accept(new_client->sock(),
           boost::bind(handle_accept,new_client,_1));
   }
   int main(int argc, char* argv[]) {
       talk_to_client::ptr client = talk_to_client::new_();
       acceptor.async_accept(client->sock(),
           boost::bind(handle_accept,client,_1));
       service.run();

}

每一次客户端连接到服务时,handle_accept被调用,它会异步地从客户端读取,然后同样异步地等待一个新的客户端。

代码

你会在这本书相应的代码中得到所有4个应用(TCP回显同步客户端,TCP回显同步服务端,TCP回显异步客户端,TCP回显异步服务端)。当测试时,你可以使用任意客户端/服务端组合(比如,一个异步客户端和一个同步服务端)。

UDP回显服务端/客户端

因为UDP不能保证所有信息都抵达接收者,我们不能保证“信息以回车结尾”。

没收到消息,我们只是回显,但是没有socket去关闭(在服务端),因为我们是UDP。

UDP同步回显客户端

UDP回显客户端比TCP回显客户端要简单:

ip::udp::endpoint ep( ip::address::from_string("127.0.0.1"), 8001);
   void sync_echo(std::string msg) {
       ip::udp::socket sock(service, ip::udp::endpoint(ip::udp::v4(), 0)
   );
       sock.send_to(buffer(msg), ep);
       char buff[1024];
       ip::udp::endpoint sender_ep;
       int bytes = sock.receive_from(buffer(buff), sender_ep);
       std::string copy(buff, bytes);
       std::cout << "server echoed our " << msg << ": "
                   << (copy == msg ? "OK" : "FAIL") << std::endl;
       sock.close();
   }
   int main(int argc, char* argv[]) {
       char* messages[] = { "John says hi", "so does James", "Lucy got
   home", 0 };
       boost::thread_group threads;
       for ( char ** message = messages; *message; ++message) {
           threads.create_thread( boost::bind(sync_echo, *message));
           boost::this_thread::sleep( boost::posix_time::millisec(100));
       }
       threads.join_all();
   }

所有的逻辑都在synch_echo()中;连接到服务端,发送消息,接收服务端的回显,然后关闭连接。

UDP同步回显服务端

UDP回显服务端会是你写过的最简单的服务端:

io_service service;
   void handle_connections() {
       char buff[1024];
       ip::udp::socket sock(service, ip::udp::endpoint(ip::udp::v4(),
   8001));
       while ( true) {
           ip::udp::endpoint sender_ep;
           int bytes = sock.receive_from(buffer(buff), sender_ep);
           std::string msg(buff, bytes);
           sock.send_to(buffer(msg), sender_ep);

} }

   int main(int argc, char* argv[]) {
       handle_connections();

}

它非常简单,而且能很好的自释。

我把异步UDP客户端和服务端留给读者当作一个练习。

总结

我们已经写了完成的应用,最终让Boost.Asio得以工作。回显应用是开始学习一个库时非常好的工具。你可以经常学习和运行这个章节所展示的代码,这样你就可以非常容易地记住这个库的基础。

在下一章,我们会建立更复杂的客户端/服务端应用,我们要确保避免低级错误,比如内存泄漏,死锁等等。

时间: 2024-08-19 04:17:56

Boost.Asio c++ 网络编程翻译(16)的相关文章

Boost.Asio c++ 网络编程翻译(1)

第一次翻译,希望大家多多指正 实战出精华 Boost.Asio C++ 网络编程 用具体的C++网络编程例子来提升你的技能 John Torjan 用具体的C++网络编程例子来提升你的技能 Copyright ? 2013 Packt Publishing 版权所有,除了在鉴定文章或者评论中进行简单引用,如果没有经过出版者事先的书面授权,该书的任何部分都不能被转载.存储在检索系统中.或者以任何形式和方式传阅. 在这本书准备发行之前,我们已经尽我们最大的努力去保证书中信息的准确性.但是,这本书中包

Boost.Asio c++ 网络编程翻译(20)

异步服务端 这个图表是相当复杂的:从Boost.Asio出来你可以看到4个箭头指向on_accept,on_read,on_write和on_check_ping.着也就意味着你永远不知道哪个异步调用是下一个完成的调用,但是你可以确定的是它是这4个操作中的一个. 现在,我们是异步的了:我们可以继续保持单线程.接受客户端连接是最简单的部分,如下所示: ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(), 8001)

Boost.Asio c++ 网络编程翻译(30)[完结]

PS:至此终于完成了Boost.Asio C++ network programming一书的翻译,这是我人生第一本完整翻译的书,从开始的磕磕绊绊,到最后小有心得,我收获很多.我将把这个系列的博客进行整理和校对,希望有兴趣的人可以帮我一起,来给大家提供更好更专业的阅读体验. 句柄追踪信息到文件 默认情况下,句柄的追踪信息被输出到标准错误流(相当于std::cerr).你想把输出重定向到其他地方的可能性是非常高的.对于控制台应用,输出和错误输出都被默认输出到相同的地方,也就是控制台.但是对于一个w

Boost.Asio c++ 网络编程翻译(14)

保持活动 假如,你需要做下面的操作: io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, buffer(buff)); 在这个例子中,sock和buff的存在时间都必须比read()调用的时间要长.也就是说,在调用read()返回之前,它们都必须有效.这就是你期望的:你传给一个方法的所有参数在参数内部都必须有效.当我们采用异步方式时,事情会变得越复杂. io_service servi

Boost.Asio c++ 网络编程翻译(3)

Boost.Asio入门 什么是Boost.Asio 简单来说,Boost.Asio是一个跨平台的.主要用于网络和其他一些底层输入/输出编程的C++库. 计算机网络的设计方式有很多种,但是Boost.Asio的的方式远远优于它们.它在2005年就被包含进Boost,然后被广大Bosot的用户测试并在很多项目中使用,比如Remobo(http://www.remobo.com),可以让你创建你自己的即时私有网络(IPN),libtorrent(http://www.rasterbar.com/pr

Boost.Asio c++ 网络编程翻译(11)

*_at方法 这些方法在一个流上面做随机存取操作.你来指定read和write操作从什么地方開始(offset): async_read_at(stream, offset, buffer [, completion], handler):这种方法在一个指定的流上从offset处開始运行一个异步的read操作,当操作结束时,他会调用handler. handler的格式为:void handler(const boost::system::error_code&  err, size_t byt

Boost.Asio c++ 网络编程翻译(26)

Boost.Asio-其他特性 这章我们讲了解一些Boost.Asio不那么为人所知的特性.标准的stream和streambuf对象有时候会更难用一些,但正如你所见.它们也有它们的益处.最后,你会看到姗姗来迟的Boost.Asio协程的入口,它能够让你的异步代码变的很易读.这是很惊人的一个特性. 标准stream和标准I/O buffer 读这一章节之前你须要对STL stream和STL streambuf对象有所了解. Boost.Asio在处理I/O操作时支持两种类型的buffer: b

Boost.Asio c++ 网络编程翻译(6)

io_service类 你应该已经发现大部分使用Boost.Asio编写的代码都会使用几个ios_service的实例.ios_service是这个库里面最重要的类:它负责和操作系统打交道,等待所有异步操作的结束,然后为每一个异步操作调用完成处理程序. 如果你选择用同步的方式来创建你的应用,你不需要考虑我将在这一节向你展示的东西. 你可以用几种不同的方式来使用io_service.在下面的例子中,我们有3个异步操作,2个socket连接和一个计时器等待: 有一个io_service和一个处理线程

Boost.Asio c++ 网络编程翻译(7)

Boost.Asio基本原理 这一章涵盖了你使用Boost.Asio时必须知道的一些事情.我们也将深入研究比同步编程更机警.更有乐趣的异步编程. 网络API 这一部分包含了当使用Boost.Asio编写网络应用程序时你必须知道的事情. Boost.Asio命名空间 Boost.Asio的一切都需要包含在boost::asio的命名空间或者其子命名空间内. boost::asio:这是核心类和函数所在的地方.重要的类有io_service和streambuf.类似read, read_at, re