2011-07-18 9 views
6

Piszę serwer (głównie dla systemu Windows, ale byłoby fajnie, gdybym mógł go utrzymać na wielu platformach) i po prostu używam do tego zwykłego okna konsoli. Jednak chcę, aby serwer mógł wykonywać polecenia takie jak: text_to_say_here lub kick playername itd. Jak mogę mieć asynchroniczne wejście/wyjście? Próbowałem już trochę rzeczy z normalnymi printf() i gets_s, ale to spowodowało kilka naprawdę ... dziwnych rzeczy.C++ Wprowadzanie i wyprowadzanie do okna konsoli w tym samym czasie

mam na myśli coś takiego 1

podziękowania.

+0

co "dziwne rzeczy"? – NPE

+0

[Bezwstydna wtyczka] (https://github.com/louisdx/schlagwetter) :-) –

+0

po prostu symulować obsługę przerwań. będziesz dobry, aby iść, jak sądzę. –

Odpowiedz

0

Możesz spróbować umieścić dane wejściowe i wyjściowe w osobnych wątkach. Nie jestem do końca pewien, dlaczego chcesz to zrobić, ale wątki powinny wykonać to zadanie. :)

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

+1

Och, noes! bez gwintowania dla IO, to powinno być asynchroniczne! – piotr

+0

Cóż, przetwarzanie asynchroniczne to wątkowanie, prawda? –

+0

Tak, operacje asynchroniczne są często wykonywane z wątkami, ale problem polega na tym, że standardowe operacje we/wy biblioteki nie są bezpieczne dla wielu wątków ... więc wiele wątków próbujących odczytać i zapisać na konsoli spowoduje różnego rodzaju nieparzyste i nieprzewidywalne przeplatanie się zapisów. W związku z tym przed przejściem do operacji we/wy należy wdrożyć pewien rodzaj blokowania. – Jason

3

Można symulować asynchronicznego I/O przy użyciu wątków, ale co ważniejsze, trzeba dzielić mutex między dwoma odczytu/zapisu wątki w celu uniknięcia problemów z wejściem na inny wątek wątku i zapisywanie na konsoli na wyjściu innego wątku. Innymi słowy std::cout, std::cin, fprintf(), itd. Nie są multi-thread bezpieczne, a w rezultacie otrzymasz nieprzewidywalne przeplatania wzór między dwoma operacjami, gdy odczyt lub zapis odbywa się podczas odczytu lub zapisu kolejna już dzieje. Możesz łatwo skończyć czytaniem, próbując zająć miejsce w trakcie pisania, a ponadto, gdy wpisujesz dane wejściowe na konsoli, kolejna nić do pisania może zacząć pisać na konsoli, tworząc wizualny bałagan "próbuję wpisać jako dane wejściowe.

Aby poprawnie zarządzać asynchronicznymi wątkami odczytu i zapisu, najlepiej jest ustawić dwie klasy, jedną do czytania, a drugą do pisania. W każdej klasie skonfiguruj kolejkę komunikatów, która będzie przechowywać wiadomości (najprawdopodobniej std::string) dla głównego wątku do pobrania w przypadku przeczytanego wątku, a dla wątku głównego do przekazywania wiadomości w przypadku wątku zapisu. Możesz również utworzyć specjalną wersję swojego przeczytanego wątku, która może wydrukować monit, a wiadomość zostanie wepchnięta do kolejki komunikatów przez główny wątek, który wyświetli monit przed przeczytaniem z poziomu stdin lub std::cin. Obie klasy będą następnie udostępniać wspólny muteks lub semafor, aby zapobiec nieprzewidywalnemu przeplataniu operacji we/wy. Blokując wspólny muteks przed wywołaniami iostream (odblokowując go później), uniknie się nieprzewidywalnego przeplatania wejść/wyjść. Każdy wątek doda także inny muteks, który jest unikalny dla każdego wątku, który może być użyty do utrzymania wyłączności przez dostęp do wewnętrznej kolejki komunikatów klasy. Na koniec można wdrożyć kolejki komunikatów w każdej klasie jako std::queue<std::string>.

Jeśli chcesz, aby twój program był jak najbardziej wieloplatformowy, sugerowałbym implementację tego przy pomocy wątków Boost :: threads lub przy użyciu nowych bibliotek C++ 0x std :: threads.

1

Jeśli rowu okno konsoli i korzystać z połączeń TCP dowodzenia i kontroli, serwer będzie znacznie łatwiejsze do utrzymania dla wielu platform, a także prostsze i bardziej elastyczne.

4

Krótki kod, aby skorzystać z funkcji C++ 11 (to jest cross-platform)

#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; 
} 
Powiązane problemy