Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost ASIO-如何编写控制台服务器2_C++_Console Application_Boost Asio_Nonblocking - Fatal编程技术网

C++ Boost ASIO-如何编写控制台服务器2

C++ Boost ASIO-如何编写控制台服务器2,c++,console-application,boost-asio,nonblocking,C++,Console Application,Boost Asio,Nonblocking,我正试图编写一个在Ubuntu服务器上运行的游戏服务器(没有GUI),但我在第一步遇到了问题。我是C++新手,请跟我说。< /P> 我需要能够在服务器继续运行时,在任何给定点向服务器键入命令。因为cin是一个阻塞输入,所以它不会飞。我已经四处挖掘,似乎应该使用Boost的ASIO库 非常接近满足我的需求,但我还需要知道两件事: 1:从输入传递的“命令”似乎一次仅限于1个字符。我需要的不仅仅是单键输入,例如“shutdown”、“say'helloworld!”、“listPlayers-onli

我正试图编写一个在Ubuntu服务器上运行的游戏服务器(没有GUI),但我在第一步遇到了问题。我是C++新手,请跟我说。< /P> 我需要能够在服务器继续运行时,在任何给定点向服务器键入命令。因为cin是一个阻塞输入,所以它不会飞。我已经四处挖掘,似乎应该使用Boost的ASIO库

非常接近满足我的需求,但我还需要知道两件事:

1:从输入传递的“命令”似乎一次仅限于1个字符。我需要的不仅仅是单键输入,例如“shutdown”、“say'helloworld!”、“listPlayers-online”等等。我尝试将代码修改为使用字符串,而不是字符:

#include <boost/asio.hpp>

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

#include <iostream>
#include <string>

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.compare( "\n" ) != 0 ) {
            std::cout << "command: " << _command << std::endl;
        }

        this->read();
    }

private:
    posix::stream_descriptor _input;
    std::string _command;
};



int main()
{
    io_service io_service;
    Input::create( io_service );
    io_service.run();
}
即使其他一切正常,在正常情况下,控制仍然无法到达mainLoop()。换句话说,
io\u service.run()
仍在阻塞,无法实现全部目的。这显然不是实现io_服务和/或mainLoop()的正确方法;那是什么呢


如果已经这样做了数千次,我深表歉意,但显然我没有用谷歌搜索正确的短语来显示我正在寻找的结果。

boost::asio::buffer
不直接支持从
std::string
创建可变缓冲区,主要是因为它们不能保证在C++11之前的内存中是连续的

您调用它的方式(
(void*,size\t)
重载),您将让读取覆盖std::string的内部,这将导致您的错误。您可能应该使用此列表中的其他重载之一:-最有可能的重载是
std::vector
,因为当读取返回时,您可以轻松地将其复制到字符串中

现在的问题是,您需要事先知道要读取多少个字符,因为字符串的长度是可变的。为此,在读取实际内容之前,需要分别读取长度。然后调整缓冲区的大小(如我所说,很可能是
std::vector
),并安排读取该长度。请注意,发送方可以同时发送这两个消息,这只是从流中读取消息时比较复杂。。。总结:

  • async\u将字符串长度读入固定长度的整数
  • 为读取的内容适当调整缓冲区大小
  • 异步读取您的内容

  • 至于你的第二个问题,你想要什么还不是很清楚,但是如果你想在asio运行的时候做你自己的事情,你可能需要研究一下
    io服务::poll()

    boost::asio::buffer
    不直接支持从
    std::string
    创建可变缓冲区,主要是因为它们不能保证在C++11之前的内存中是连续的

    您调用它的方式(
    (void*,size\t)
    重载),您将让读取覆盖std::string的内部,这将导致您的错误。您可能应该使用此列表中的其他重载之一:-最有可能的重载是
    std::vector
    ,因为当读取返回时,您可以轻松地将其复制到字符串中

    现在的问题是,您需要事先知道要读取多少个字符,因为字符串的长度是可变的。为此,在读取实际内容之前,需要分别读取长度。然后调整缓冲区的大小(如我所说,很可能是
    std::vector
    ),并安排读取该长度。请注意,发送方可以同时发送这两个消息,这只是从流中读取消息时比较复杂。。。总结:

  • async\u将字符串长度读入固定长度的整数
  • 为读取的内容适当调整缓冲区大小
  • 异步读取您的内容
  • 至于你的第二个问题,现在还不清楚你想要什么,但是如果你想在asio运行时做自己的事情,你可能需要研究一下
    io\u service::poll()

  • boost::asio::buffer(&_命令,sizeof(_命令))
    意味着您希望覆盖
    \u命令
    对象的前4个字节(或任何
    sizeof(string)
    是什么),但这显然不是您想要的。如果需要自动调整输入缓冲区大小,请改用
    asio::streambuf

  • io_service::run
    阻塞调用线程,因此您的
    mainLoop
    将不会运行。您可以在单独的线程中执行
    io_service::run
    ,也可以手动轮询
    io_serivce
    ,将对
    run_one
    /
    poll_one
    的调用与您自己的应用程序循环的迭代交错进行

  • boost::asio::buffer(&_命令,sizeof(_命令))
    意味着您希望覆盖
    \u命令
    对象的前4个字节(或任何
    sizeof(string)
    是什么),但这显然不是您想要的。如果需要自动调整输入缓冲区大小,请改用
    asio::streambuf

  • io_service::run
    阻塞调用线程,因此您的
    mainLoop
    将不会运行。您可以在单独的线程中执行
    io_service::run
    ,也可以手动轮询
    io_serivce
    ,将对
    run_one
    /
    poll_one
    的调用与您自己的应用程序循环的迭代交错进行


  • 官方的例子对你没有帮助吗?或者不是特别的。虽然我相信它们对精通C++的人是有用的,但对我来说却是信息过载。我几乎不知道我想要的效果是什么,所以查找一个例子是有问题的。最重要的是,我无法了解代码在做什么,更不用说哪部分有我想要的效果了。简言之,为了理解boost的使用情况,我真的需要将它缩小到与我的目标非常接近的范围。boost官方示例对您有帮助吗?或者不是特别的。虽然我确信它们对精通C++的人是有用的,但是
    bool loopControl = true;
    
    int main()
    {
        io_service io_service;
        Input::create( io_service );
    
        // This loops continually until the server is commanded to shut down
        while( loopControl )
        {
            io_service.run();      // Handles async input 
            mainLoop();            // Where my actual program resides
        }
    }