BOOST ASIO - 如何写控制台服务器BOOST ASIO - 如何写控制台服务器(BOO

2019-05-12 04:12发布

我必须写异步TCP Sever的。 TCP服务器必须通过管理控制台(用于如:删除客户端,所有连接的客户端的显示列表中,ETCC ..)

问题是:我怎么能把(或写)控制台,它可以在上面的功能调用。 此控制台必须是一个客户端? 我应该运行此控制台客户端作为sepearate线程?

我读了很多的教程和我couldn`t找到一个解决我的问题。

ServerTCP代码

class ServerTCP
{
public:
   ServerTCP(boost::asio::io_service& A_ioService, unsigned short A_uPortNumber = 13)
      : m_tcpAcceptor(A_ioService, tcp::endpoint(tcp::v4(), A_uPortNumber)), m_ioService (A_ioService)
   {
      start();
   }
private:

   void start()
   {
      ClientSessionPtr spClient(new ClientSession(m_tcpAcceptor.io_service(), m_connectedClients));

      m_tcpAcceptor.async_accept(spClient->getSocket(), 
                                 boost::bind(&ServerTCP::handleAccept, this, spClient, 
                                 boost::asio::placeholders::error));

   }
   void handleAccept(ClientSessionPtr A_spNewClient,  const boost::system::error_code& A_nError)
   {
      if ( !A_nError )
      {
         A_spNewClient->start();
         start();
      }
   }



   boost::asio::io_service& m_ioService;
   tcp::acceptor            m_tcpAcceptor;
   Clients                  m_connectedClients;
};

主功能:

   try
   {
      boost::asio::io_service ioService;

      ServerTCP server(ioService);
      ioService.run();  
   }
   catch (std::exception& e)
   {
      std::cerr << "Exception: " << e.what() << "\n";
   }

您好萨姆。 谢谢你的答复。 你可能会这么好心给我看一个部分的代码或一些链接的例子涉及这个问题? Propably,我不`吨正确理解“......单线程服务器...”

在“控制台”事实,我要管理服务器的操作,我需要一个像下面SMT:

main()

cout << "Options: q - close server, s - show clients";
while(1)
{
  char key = _getch();
  switch( key )
  {
      case 'q':
         closeServer();
      break
      case 's':
         showClients();
      break
  } 
}

Answer 1:

问题是:我怎么能把(或写)控制台,它可以在上面的功能调用。 此控制台必须是一个客户端? 我应该运行此控制台客户端作为sepearate线程?

你并不需要一个单独的线程,使用posix::stream_descriptor和分配 STDIN_FILENO它。 使用async_read和处理在读取处理的请求。

#include <boost/asio.hpp>

#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>

using namespace boost::asio;

class Input : public boost::enable_shared_from_this<Input>
{
public:
    typedef boost::shared_ptr<Input> Ptr;

public:
    static void create(
            io_service& io_service
            )
    {
        Ptr input(
                new Input( io_service )
                );
        input->read();
    }

private:
    explicit Input(
            io_service& io_service
         ) :
        _input( io_service )
    {
        _input.assign( STDIN_FILENO );
    }

    void read()
    {
        async_read(
                _input,
                boost::asio::buffer( &_command, sizeof(_command) ),
                boost::bind(
                    &Input::read_handler,
                    shared_from_this(),
                    placeholders::error,
                    placeholders::bytes_transferred
                    )
                );
    }

    void read_handler(
            const boost::system::error_code& error,
            size_t bytes_transferred
            )
    {
        if ( error ) {
            std::cerr << "read error: " << boost::system::system_error(error).what() << std::endl;
            return;
        }

        if ( _command != '\n' ) {
            std::cout << "command: " << _command << std::endl;
        }

        this->read();
    }

private:
    posix::stream_descriptor _input;
    char _command;
};

int
main()
{
    io_service io_service;
    Input::create( io_service );
    io_service.run();
}


Answer 2:

如果我理解正确的OP,他/她想要运行通过控制台即控制台作为用户界面控制异步TCP服务器。 在这种情况下,你不需要单独的客户端应用程序查询服务器连接的客户端,等:

  • 你需要生成一个线程,不知怎的,调用io_service对象:: run方法。 目前,您是从主调用此。 由于您的服务器可能会在主要的作用域,你需要像做一个参考传递到服务器到新的线程。 io_service对象可以是例如服务器类的成员(除非你的应用有其他要求在这种情况下,通过服务器和io_service对象的新线程)。
  • 添加相应的方法,如showClients,closeServer,等你的服务器类
  • 确保这些调用,它们通过控制台触发是线程安全的
  • 在closeServer方法你可以为实例调用io_service对象::停止,这将导致在结束服务器。


文章来源: BOOST ASIO - How to write console server