2

Ubuntu サーバー (GUI なし) で実行するゲーム サーバーを作成しようとしていますが、ステップ 1 で問題が発生しています。C++ は初めてなので、ご容赦ください。

サーバーが実行を続けている間、任意の時点でサーバーにコマンドを入力できる必要があります。cin はブロッキング入力なので、飛びません。いろいろ調べてみたところ、Boost の ASIO ライブラリを使用するのがよいようです。

この答えは私のニーズを満たすことに非常に近づいていますが、さらに 2 つのことを知る必要があります。

1: 入力から渡される「コマンド」は、一度に 1 文字に制限されているようです。「shutdown」、「say 'Hello World!'」、「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();
}

ただし、これにより、数文字の入力後にセグメンテーション エラーが発生し、入力後に Enter キーを押すと、「command:」が表示されなくなりました。このセットアップで文字列を使用する方法はありますか? それらを一度に1文字ずつ別の文字列に追加するとうまくいくと確信していますが、この設定は文字列全体でネイティブに機能すると思います。

2: (明確化のために編集) サーバー コードの残りの部分と連携して動作するには、このノンブロッキング入力が必要です。問題は、そのコードはどこに行くのかということです。上記の main() 関数に注目して、while ループを使用するように変更し、mainLoop 関数を呼び出します。

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
    }
}

他のすべてが機能したとしても、通常の状況では制御が mainLoop() に到達することはありません。言い換えれば、io_service.run()まだブロックされており、目的全体が無効になっています。これは明らかに io_service や mainLoop() を実装する正しい方法ではありません。だから何ですか?

これが何千回も行われている場合は申し訳ありませんが、探している結果を表示するための適切なフレーズをグーグルで検索していないようです。

4

2 に答える 2

0

boost::asio::bufferからのミュータブル バッファの作成を直接サポートしていませんstd::string。これは主に、C++11 より前のメモリで連続しているとは保証されていないためです。

あなたがそれを呼び出す方法((void*, size_t)オーバーロード)では、読み取りにstd::stringの内部を上書きさせ、セグメンテーション違反につながります。おそらく、このリストにある他のオーバーロードのいずれかを使用する必要があります: http://www.boost.org/doc/libs/1_50_0/doc/html/boost_asio/reference/buffer.htmlstd::vector<char>読み取りが返されたら、それを文字列にコピーします。

問題は、文字列が可変長であるため、読み取る文字数を事前に知る必要があることです。そのためにはasync_read、実際の内容を読む前に、別途長さにする必要があります。次に、バッファーのサイズを変更し (私が言ったように、おそらくstd::vector<char>)、その長さの読み取りをスケジュールします。送信者は両方を一緒に送信できることに注意してください。これは、ストリームから読み取る場合にのみ複雑です...要約するには:

  1. async_read 文字列の長さを固定長の整数に変換する
  2. 適切に読み取られたコンテンツのバッファのサイズを変更します
  3. async_read コンテンツ

2番目の質問については、何をしたいのかはっきりしていませんがio_service::poll()、asioの実行中に自分で何かをしたい場合は調べてみてください。

于 2012-07-12T08:38:56.127 に答える
0
  1. boost::asio::buffer( &_command, sizeof(_command) )オブジェクトの最初の 4 バイト (または何でもsizeof(string))を上書きすることを意味します_commandが、これは明らかにあなたが望むものではありません。自動サイズ変更入力バッファーが必要な場合は、asio::streambuf代わりに使用してください。

  2. io_service::run 呼び出しスレッドをブロックmainLoopするため、実行されません。別のスレッドで実行するか、手動でio_service::runポーリングして、 /への呼び出し(リファレンスを参照) を独自のアプリケーション ループの繰り返しでio_serivceインターリーブすることができます。run_onepoll_one

于 2013-01-19T20:57:09.140 に答える