我正在尝试编写一个在 Ubuntu Server(无 GUI)上运行的游戏服务器,但我在第 1 步遇到了问题。我是 C++ 新手,所以请多多包涵。
我需要能够在服务器继续运行时在任何给定点向服务器键入命令。由于 cin 是一个阻塞输入,所以它不会飞。我已经挖掘了,似乎要走的路是使用 Boost 的 ASIO 库。
这个答案非常接近满足我的需求,但我仍然需要知道另外两件事:
1:从输入传递的“命令”似乎一次限制为 1 个字符。我需要的不仅仅是单键输入,例如“shutdown”、“say 'Hello World!'”、“listPlayers -online”等。我尝试修改代码以使用字符串,而不是 char:
#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();
}
但是,这会在输入几个字符后导致分段错误,并且在输入任何输入后按回车不再导致“命令:”出现。有没有办法让这个设置使用字符串?我确信一次将它们附加到一个单独的字符串中会起作用,但我想认为这种设置可以在本机上与整个字符串一起使用。
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(); 的正确方法;那是什么?
如果这已经完成了数千次,我深表歉意,但显然我没有在谷歌上搜索正确的短语来显示我正在寻找的结果。