我正在编写一个服务器(主要用于Windows,但如果我可以保持多平台,那将会很酷)我只是使用一个普通的控制台窗口。但是,我希望服务器能够执行诸如text_to_say_here或kick playername等命令。我怎样才能有异步输入/输出?我已经用普通的printf()和gets_s尝试了一些东西但是这导致了一些非常奇怪的东西。
我的意思是1
感谢。
答案 0 :(得分:6)
利用C ++ 11功能(即跨平台)的快速代码
#include <atomic>
#include <thread>
#include <iostream>
void ReadCin(std::atomic<bool>& run)
{
std::string buffer;
while (run.load())
{
std::cin >> buffer;
if (buffer == "Quit")
{
run.store(false);
}
}
}
int main()
{
std::atomic<bool> run(true);
std::thread cinThread(ReadCin, std::ref(run));
while (run.load())
{
// main loop
}
run.store(false);
cinThread.join();
return 0;
}
答案 1 :(得分:3)
您可以使用线程模拟异步I / O,但更重要的是,您必须在两个读/写线程之间共享一个互斥锁,以避免线程踩到另一个线程时出现任何问题,并在顶部写入控制台另一个线程的输出。换句话说,std::cout
,std::cin
,fprintf()
等不是多线程安全的,因此,您将在两个操作之间获得不可预测的交错模式,其中读取或写入发生在另一个读或写已经发生的时候。您可能很容易在读取过程中尝试进行读取操作,而且,当您在控制台上键入输入时,另一个写入线程可能会开始在控制台上写入,使您看起来很乱我试图输入。
为了正确管理异步读写线程,最好设置两个类,一个用于读取,另一个用于写入。在每个类中,设置一个消息队列,该消息队列将存储消息(很可能是std::string
),以便在读取线程的情况下检索主线程,并且主线程在以下情况下将消息推送到写线程。您可能还想创建一个可以打印提示的读取线程的特殊版本,主线程将消息推送到其消息队列中,在从stdin
或std::cin
读取之前将打印提示。然后,这两个类将共享一个公共互斥锁或信号量,以防止I / O的不可预测的交错。通过在任何iostream
调用之前锁定公共互斥锁(之后将其解锁),将避免任何不可预测的I / O交错。每个线程还将添加另一个互斥锁,该互斥锁对于每个线程都是唯一的,可用于维护对该类内部消息队列的访问权限的独占性。最后,您可以将每个类中的消息队列实现为std::queue<std::string>
。
如果你想让你的程序尽可能跨平台,我建议用Boost :: threads或者使用新的C ++ 0x std :: threads库来实现它。
答案 2 :(得分:1)
如果您放弃控制台窗口并使用TCP连接进行命令和控制,您的服务器将更容易保持多平台,并且更简单,更灵活。
答案 3 :(得分:0)
您可以尝试将输入和输出放在不同的线程上。我不太确定你为什么要这样做,但线程应该做的工作。 :)