2011-07-18 12 views
6

Estoy escribiendo un servidor (principalmente para Windows, pero sería genial si pudiera mantenerlo multiplataforma) y solo uso una ventana de consola normal para él. Sin embargo, quiero que el servidor pueda hacer comandos como, por ejemplo, text_to_say_here o kick playername, etc. ¿Cómo puedo tener una entrada/salida asíncrona? Ya probé algunas cosas con el printf() normal y gets_s, pero eso dio como resultado algunas cosas realmente ... extrañas.C++ Entrada y salida a la ventana de la consola al mismo tiempo

me refiero a algo como esto 1

gracias.

+0

Qué "cosas raras"? – NPE

+0

[Plug Shameless] (https://github.com/louisdx/schlagwetter) :-) –

+0

simplemente simula un manejador de interrupciones. estarás listo para irte, supongo. –

Respuesta

0

Puede intentar colocar la entrada y salida en hilos separados. No estoy muy seguro de por qué quieres hacer esto, pero el enhebrado debería hacer el trabajo. :)

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

+1

¡Oh, no! ¡no enhebrar para IO, eso debería ser asincrónico! – piotr

+0

Bueno, un procesamiento tan sofisticado está enhebrando ahora ¿no? –

+0

Sí, las operaciones asincrónicas a menudo se realizan con subprocesos, pero el problema es el hecho de que las operaciones de E/S de biblioteca estándar no son multithread-safe ... por lo que varios subprocesos que intenten leer y escribir en la consola causarán todo tipo de impares e intercalación impredecible de escrituras. Por lo tanto, debe implementar algún tipo de bloqueo antes de acceder a una operación de E/S. – Jason

3

Puede simular E/S asíncrona utilizando hilos, pero lo más importante, debe compartir un mutex entre los dos de lectura/escritura hilos con el fin de evitar cualquier problema con un hilo de inspección en otro hilo, y escribir en la consola encima de la salida de otro hilo. En otras palabras, std::cout, std::cin, fprintf(), etc. no son seguros para múltiples hilos, y como resultado, obtendrá un patrón de intercalación impredecible entre las dos operaciones donde se realiza una lectura o escritura mientras otra lectura o escritura ya estaba ocurriendo. Puede terminar fácilmente con una lectura que intenta tener lugar en medio de una escritura, y además, mientras escribe una entrada en la consola, otro hilo de escritura podría comenzar a escribirse en la consola, haciendo un desorden visual de lo que Estoy tratando de escribir como entrada.

Para gestionar adecuadamente sus subprocesos de lectura y escritura asincrónicos, sería mejor configurar dos clases, una para lectura y otra para escritura. En cada clase, configure una cola de mensajes que almacenará mensajes (lo más probable es std::string) para el hilo principal a recuperar en el caso del hilo de lectura, y para el hilo principal para enviar mensajes a en el caso del hilo de escritura. También es posible que desee crear una versión especial de su hilo de lectura que pueda imprimir un mensaje, con un mensaje insertado en su cola de mensajes por el hilo principal que imprimirá un mensaje antes de leer desde stdin o std::cin. Ambas clases compartirán un mutex o semáforo común para evitar intercalaciones impredecibles de E/S. Al bloquear el mutex común antes de cualquier llamada a iostream (y desbloquearlo después), se evitará cualquier intercalación impredecible de E/S. Cada subproceso también agregará otro mutex único para cada subproceso que se puede usar para mantener la exclusividad sobre el acceso a la cola de mensajes internos de la clase. Finalmente, puede implementar las colas de mensajes en cada clase como std::queue<std::string>.

Si desea que su programa sea lo más multiplataforma posible, le sugiero que implemente esto con Boost :: threads o con las nuevas bibliotecas C++ 0x std :: threads.

1

Si abandona la ventana de la consola y utiliza las conexiones TCP para el comando y control, su servidor será mucho más fácil de mantener multiplataforma, y ​​también más simple y más flexible.

4

Código rápido para aprovechar las características de C++ 11 (es decir, multiplataforma)

#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; 
} 
Cuestiones relacionadas