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() を実装する正しい方法ではありません。だから何ですか?
これが何千回も行われている場合は申し訳ありませんが、探している結果を表示するための適切なフレーズをグーグルで検索していないようです。