提高:: ASIO受体重新开放,并异步EOF之后读 [英] boost::asio acceptor reopen and async read after EOF

查看:179
本文介绍了提高:: ASIO受体重新开放,并异步EOF之后读的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可惜我已经到了一个抱我的发展,因为我无法理解TCP ::受究竟怎么了boost :: ASIO ::知识产权::应该被使用。
该TC $ P $帕德尔类的设计是一个单身主义者和标题声明以下为私有。

sadly I've come to a hold in my development since I can not understand how exactly the boost::asio::ip::tcp::acceptor is supposed to be used. The TCPReader class is designed to be a singleton and the header declares the following as private.

void runInThread();

void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred);

void accept_handler(const boost::system::error_code &ec);

boost::asio::io_service io_service;
boost::asio::io_service::work runningService;
boost::asio::ip::tcp::socket sock;
boost::asio::ip::tcp::acceptor acceptor;

bool isConnected;

<<

<<

TCPReader::TCPReader() : sock(io_service),
                        runningService(io_service),
                        acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), TCPPort)){
    this->isConnected = false;

    acceptor.async_accept(sock, boost::bind(&TCPReader::accept_handler, this, boost::asio::placeholders::error));
    boost::thread thread(boost::bind(&TCPReader::runInThread, this));
}


 void TCPReader::runInThread(){
    io_service.run();
}

在accept_handler比触发read_handler,它所有的作品像一个魅力直到read_handler收到EOF或其他错误。我想是让受回的状态下也可以接受连接像它初始化后做到了。我试图的close()取消()有以下的open()听() async_accept (如在构造)。但是,这一切似乎并没有工作。
很会AP preciate你的帮助。

the accept_handler than triggers the read_handler and it all works like a charm until the read_handler receives EOF or another error. What I want is to get the acceptor back into a state where it can accept connections like it did after initialization. I tried close() or cancel() with a following open() , listen() and async_accept(like in the constructor). But it all does not seem to work. Very much would appreciate your help.

推荐答案

该错误是发生在操作上袜子,而不是接受。因此,接受的状态应该不会受到影响。它只是需要开始与袜子在它的初始关闭状态的 async_accept 操作。

The error is occurring in an operation on sock, not acceptor. Thus, acceptor's state should not be affected. It just requires initiating an async_accept operation with sock being in its initial closed state.

下面是关于12345端口监听一个完整的基本的例子:

Here is a complete basic example that listens on port 12345:

#include <iostream>

#include <boost/array.hpp>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class tcp_reader
{
public:
  tcp_reader(boost::asio::io_service& io_service)
    : io_service_(io_service),
      socket_(io_service),
      acceptor_(io_service, 
                tcp::endpoint(tcp::v4(), 12345))
  {
    accept_connection();
  }

private:

  void accept_connection()
  {
    std::cout << "accepting connection" << std::endl;
    // Verify socket is in a closed state.
    socket_.close();
    // On success or failure, acceptor will open() socket_.
    acceptor_.async_accept(socket_,
      boost::bind(&tcp_reader::handle_accept, this,
                  boost::asio::placeholders::error));
  }

  void handle_accept(const boost::system::error_code& error)
  {
    // On error, return early.
    if (error)
    {
      std::cout << "handle_accept: " << error.message() << std::endl;
      return;
    }

    // Start reading from socket.
    read();    
  }

  void read()
  {
    std::cout << "reading from socket" << std::endl;
    async_read(socket_, boost::asio::buffer(buffer_),
      boost::asio::transfer_at_least(1),
      boost::bind(&tcp_reader::handle_read, this,
                  boost::asio::placeholders::error,
                  boost::asio::placeholders::bytes_transferred));
  }

  void handle_read(const boost::system::error_code& error,
                   std::size_t bytes_transferred)
  {
    // On error, go back to listening for a new connection.
    if (error)
    {
      std::cout << "handle_read: " << error.message() << std::endl;
      accept_connection();
      return;
    }

    // Output read data.
    std::cout.write(&buffer_[0], bytes_transferred);

    // Read data, so read some more.
    read(); 
  }

private:
  boost::asio::io_service& io_service_;
  tcp::socket              socket_;
  tcp::acceptor            acceptor_;
  boost::array<char, 1024> buffer_;
};

int main()
{
  boost::asio::io_service io_service;
  tcp_reader reader(io_service);
  io_service.run();
}

在使用它,我跑了它一个终端,并连接到端口12345,发送​​邮件,被杀,然后重新建立连接。在服务器控制台输出如下:

When using it, I ran it in one terminal, and connected to port 12345, send messages, killed connection, then reestablished a connection. The server console output was as follows:

[twsansbury@localhost]$ ./a.out 
accepting connection
reading from socket
hello
reading from socket
goodbye
reading from socket
handle_read: End of file
accepting connection
reading from socket
oh, oh no
reading from socket
handle_read: End of file
accepting connection
ctrl + c

和客户端控制台:

[twsansbury@localhost]$ nc 127.0.0.1 12345
hello        
goodbye 
ctrl + c
[twsansbury@localhost]$ nc 127.0.0.1 12345
oh, oh no
ctrl + c


要注意的一个行为细节是,虽然是 async_accept 操作可能不会等候的受体_ ,连接仍然排队。因此,如果连接已被接受,和另一客户端试图连接,然后后者客户将具有其连接待决被接受。如果这不是所需的行为,然后受体需要通过来过渡出监听状态的接近()回答图状态转换,并介绍了一些受体行为的更多细节。


One behavioral detail of which to be aware is that although an async_accept operation may not be pending on the acceptor_, connections are still being queued. Thus, if a connection has already been accepted, and another client tries to connect, then the latter client will have its connection pending to be accepted. If this is not the desired behavior, then the acceptor needs to transition out of a listening state via close(). This answer diagrams state transitions and describes some of the acceptor behavior in more detail.

这篇关于提高:: ASIO受体重新开放,并异步EOF之后读的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆