C ++ Ввод и вывод в консольное окно одновременно - PullRequest
7 голосов
/ 18 июля 2011

Я пишу сервер (в основном для Windows, но было бы здорово, если бы я мог сохранять его мультиплатформенным), и я просто использую для этого обычное консольное окно. Однако я хочу, чтобы сервер мог выполнять такие команды, как, скажем, text_to_say_here или пинать имя игрока и т. Д. Как я могу иметь асинхронный ввод / вывод? Я уже попробовал некоторые вещи с обычными printf () и gets_s, но это привело к некоторым действительно .... странным вещам.

Я имею в виду что-то вроде этого 1

спасибо.

Ответы [ 4 ]

6 голосов
/ 19 июля 2015

Быстрый код для использования возможностей 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;
}
3 голосов
/ 18 июля 2011

Вы можете смоделировать асинхронный ввод-вывод, используя потоки, но, что более важно, вы должны разделить мьютекс между двумя потоками чтения / записи, чтобы избежать любых проблем с переходом потока на другой поток и записью в консоль сверху вывода другого потока. Другими словами, std::cout, std::cin, fprintf() и т. Д. Не являются многопоточными, и в результате вы получите непредсказуемый шаблон чередования между двумя операциями, где происходит чтение или запись, в то время как другое чтение или написать уже происходило. Вы могли легко закончить чтение, пытаясь иметь место в середине записи, и, более того, пока вы печатаете ввод на консоли, другой поток записи может начать писать на консоли, создавая визуальный беспорядок того, что вы делаете. пытаюсь ввести в качестве ввода.

Чтобы правильно управлять потоками асинхронного чтения и записи, было бы лучше настроить два класса: один для чтения, а другой для записи. В каждом классе настройте очередь сообщений, в которой будут храниться сообщения (скорее всего, std::string) для основного потока для извлечения в случае потока чтения и для основного потока для отправки сообщений в случае потока записи , Возможно, вы также захотите создать специальную версию вашей ветки чтения, которая может печатать подсказку, с сообщением, помещенным в свою очередь сообщений главным потоком, который будет печатать подсказку перед чтением из stdin или std::cin. Оба класса будут совместно использовать общий мьютекс или семафор для предотвращения непредсказуемого чередования операций ввода-вывода. Блокируя общий мьютекс перед любыми вызовами iostream (разблокируя его впоследствии), можно избежать любого непредсказуемого чередования ввода / вывода. Каждый поток также добавляет еще один мьютекс, уникальный для каждого потока, который можно использовать для обеспечения исключительности доступа к внутренней очереди сообщений класса. Наконец, вы можете реализовать очереди сообщений в каждом классе как std::queue<std::string>.

Если вы хотите сделать вашу программу максимально кроссплатформенной, я бы предложил реализовать это либо с помощью Boost :: threads, либо с использованием новых библиотек C ++ 0x std :: threads.

1 голос
/ 18 июля 2011

Если вы закроете окно консоли и будете использовать TCP-соединения для управления и контроля, ваш сервер будет намного проще поддерживать в мультиплатформенном режиме, а также проще и гибче.

0 голосов
/ 18 июля 2011

Вы можете попробовать разместить вход и выход в отдельных потоках. Я не совсем уверен, почему вы хотите это сделать, но многопоточность должна делать эту работу. :)

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

...