zoukankan      html  css  js  c++  java
  • 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;page76image1880
           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_;
    

    };

    由于我们是很easy的回显服务,这里不须要一个is_started()方法。

    对每一个client,只读取它的消息,回显,然后关闭它。

    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 + "
    ");
           }
    

    stop(); }

       void on_write(const error_code & err, size_t bytes) {
           do_read();
    
    }
    对client的处理例如以下:
    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();
    

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

    代码
    你会在这本书对应的代码中得到全部4个应用(TCP回显同步client,TCP回显同步服务端。TCP回显异步client,TCP回显异步服务端)。

    当測试时,你能够使用随意client/服务端组合(比方。一个异步client和一个同步服务端)。


    UDP回显服务端/client
    由于UDP不能保证全部信息都抵达接收者,我们不能保证“信息以回车结尾”。
    没收到消息,我们仅仅是回显,可是没有socket去关闭(在服务端)。由于我们是UDP。

    UDP同步回显client
    UDP回显client比TCP回显client要简单:
    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();
    

    它非常easy,并且能非常好的自释。

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

    总结
    我们已经写了完毕的应用。终于让Boost.Asio得以工作。

    回显应用是開始学习一个库时很好的工具。你能够常常学习和执行这个章节所展示的代码,这样你就能够很easy地记住这个库的基础。

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




  • 相关阅读:
    delphi 让子窗体显示最大化
    Delphi 中拖动无边框窗口的5种方法
    Delphi 非主窗体(即子窗体)在任务栏显示按钮
    电脑快捷键大全
    picpick快捷键
    is()
    animate()
    :animated
    css() 方法返回或设置匹配的元素的一个或多个样式属性。
    outerWidth()
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7230992.html
Copyright © 2011-2022 走看看