2011-07-18 247 views
6

我正在编写一个服务器(主要用于Windows,但如果我可以保持它多平台,它会很酷),我只是使用一个正常的控制台窗口。但是,我希望服务器能够执行诸如text_to_say_here或kick playername等命令。如何获得异步输入/输出?我已经尝试了一些正常的printf()和gets_s,但是导致了一些非常奇怪的东西。C++同时输入和输出到控制台窗口

我意味着什么这个1

感谢等。

+0

什么 “奇怪的东西”? – NPE

+0

[无耻的插件](https://github.com/louisdx/schlagwetter):-) –

+0

只是模拟一个中断处理程序。我猜你会好起来的。 –

回答

0

您可以尝试将输入和输出放在单独的线程上。我不太清楚为什么你想这样做,但线程应该做这个工作。 :)

http://en.wikibooks.org/wiki/C++_Programming/Threading

+1

哦,不!不是线程的IO,应该是异步的! – piotr

+0

那么asynchnourous处理是线程现在不是吗? –

+0

是的,异步操作通常是通过线程完成的,但问题在于标准库I/O操作不是多线程安全的......所以多个线程试图读写控制台会导致各种奇怪的和不可预测的写入交错。因此您必须在访问I/O操作之前实施某种类型的锁定。 – Jason

3

您可以使用线程模拟异步I/O,但更重要的是,你必须共享两个读之间的互斥/为了避免与线程踩着其他任何问题,写线程线程,并在另一个线程的输出之上写入控制台。换句话说,std::cout,std::cin,fprintf()等不是多线程安全的,因此,在另一个读或写已经发生的两个操作之间发生读或写操作时,您将得到一个不可预测的交错模式。您可能很容易就会在写入过程中发生读取操作,此外,当您在控制台上键入输入时,另一个写入线程可能会开始在控制台上写入内容,从而导致视觉混乱正在尝试输入。

为了正确管理您的异步读写线程,最好设置两个类,一个用于读取,另一个用于写入。在每个类中,设置一个消息队列,该消息队列将存储消息(最有可能为std::string),供主线程在读取线程的情况下检索,并且主线程在写入线程的情况下推送消息。您可能还需要制作一个特殊版本的读取线程,可以打印提示信息,主要线程会将消息推入到其消息队列中,在从stdinstd::cin读取数据之前将打印提示。这两个类然后将共享一个共同的互斥或信号量以防止I/O的不可预测的交错。通过在任何iostream调用(之后解锁)之前锁定普通互斥锁,将避免任何不可预知的I/O交错。每个线程还会添加另一个互斥量,该互斥量对于每个线程都是唯一的,可用于维护对类的内部消息队列的访问权限。最后,您可以将每个类中的消息队列实现为std::queue<std::string>

如果你想让你的程序尽可能跨平台,我会建议用Boost :: threads或者使用新的C++ 0x std :: threads库来实现它。

1

如果您抛弃控制台窗口并使用TCP连接进行命令和控制,您的服务器将更容易保持多平台,并且也更简单且更灵活。

4

快速代码利用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; 
}