Многопоточная программа чата на C с использованием Pipes - PullRequest
0 голосов
/ 03 марта 2019

Для назначения класса мне необходимо разработать одну программу, которая при открытии в двух отдельных окнах позволяет пользователю печатать в одном окне, а введенный текст появляется в другом, в то время как в другом окне также можно набиратьи их текст появится в первом окне.

Сначала это было реализовано с использованием двух отдельных программ, одна из которых считывала ввод из stdin, записывала его в канал, называемый fflush на канале, затем получала данные из канала и помещала их в stdout перед вызовом fflush onstdout, а другой, который сделал в основном с точностью до наоборот.

Я здесь, потому что я изо всех сил пытаюсь заставить работать единственную версию программы, и я не уверен, правильно ли я понимаю многопоточность.

Вот моя основная функция:

int main()
{
    pthread_t threadID[2];

    pthread_mutex_init(&globalLock, NULL);

    pthread_create(&threadID[0], NULL, InputToPipe, NULL);
    pthread_create(&threadID[1], NULL, PipeToOutput, NULL);

    pthread_join(threadID[0], NULL);
    pthread_join(threadID[1], NULL);

    pthread_mutex_destroy(&globalLock);

    return 0;
}

Насколько я понимаю, это инициализирует глобальную блокировку (которая, я не уверен, нужна мне или нет), а затем создает два потока.Первый поток вызовет InputToPipe, а второй вызовет PipeToOutput.Оба должны ввести свои соответствующие функции почти одновременно.Однажды в InputToPipe (который выглядит следующим образом)

void *InputToPipe()
{
    pthread_mutex_lock(&globalLock);
    char buffer[100];
    FILE *output = fopen("my.pipe2", "w");
    if (output == NULL)
    {
        printf("Error opening pipe\n");
        return NULL;
    }

    while (fgets(buffer, sizeof(buffer), stdin))
    {
        fputs(buffer, output);
        fflush(output);
    }
    pthread_mutex_unlock(&globalLock);

    return NULL;
}

Установлена ​​блокировка, предназначенная для предотвращения доступа второго экземпляра программы к первой функции.Я думал, что это приведет к тому, что второй экземпляр программы будет запускать только функцию PipeToOutput (как показано ниже),

void *PipeToOutput()
{
    char buffer[100];
    FILE *input = fopen("my.pipe", "r");
    if (input == NULL)
    {
        printf("Error opening pipe\n");
        return NULL;
    }

    while (fgets(buffer, sizeof(buffer), input))
    {
        fputs(buffer, stdout);
        fflush(stdout);
    }

    return NULL;
}

, но вместо этого я думаю, что вторая программа будет блокировать выполнение каких-либо действий, поскольку первый каналприсоединяется первым, и это не может быть сделано до тех пор, пока оно не будет разблокировано первой программой, что не произойдет до ее завершения.Излишне говорить, что я запутался и почти уверен, что большая часть моей логики отключена, но я не смог найти примеров или объяснений по поводу использования двух потоков для запуска двух разных функций в двух разных окнах консоли (если только я полностью не неправильно понял назначение иэто просто одна функция, выполняемая дважды, но я не думаю, что это так).Я был бы признателен за помощь в исправлении этой программы, чтобы я мог использовать ее в качестве примера, чтобы понять, что делают потоки, или просто за объяснение того, как я буду реализовывать потоки и почему.Я знаю, что это, вероятно, глупо просто, но у меня возникли проблемы с концепцией.Заранее спасибо.

1 Ответ

0 голосов
/ 04 марта 2019

Если идея заключается в том, что my.pipe используется для передачи сообщений из первой программы во вторую, а my.pipe2 используется для передачи сообщений в обратном направлении, тогда кажется, что обе программы должны быть идентичны кроме swapping my.pipe и my.pipe2.

Похоже, они хотят, чтобы каждая программа имела два потока, один из которых отвечает за чтение из первого канала и запись в stdout, идругой отвечает за чтение из stdin и запись во второй канал.

В этом случае ваши существующие функции выглядят корректно, за исключением того, что вам вообще не нужна блокировка - все, что она делает, этоостановка обоих потоков от одновременного запуска, и ваши потоки вообще не делятся никаким состоянием.Ваша вторая копия программы будет такой же, за исключением замены my.pipe и my.pipe2 вокруг.

Обратите внимание, что ваши функции InputToPipe и PipeToOutput содержат идентичный цикл, который отличается только в FILE *используемые переменные, так что вы можете разделить это на собственную функцию:

void FileToFile(FILE *output, FILE *input)
{
    char buffer[100];

    while (fgets(buffer, sizeof(buffer), input))
    {
        fputs(buffer, output);
        fflush(output);
    }
}

void *InputToPipe()
{
    FILE *output = fopen("my.pipe2", "w");
    if (output == NULL)
    {
        printf("Error opening pipe\n");
        return NULL;
    }

    FileToFile(output, stdin);

    fclose(output);
    return NULL;
}

void *PipeToOutput()
{
    FILE *input = fopen("my.pipe", "r");
    if (input == NULL)
    {
        printf("Error opening pipe\n");
        return NULL;
    }

    FileToFile(stdout, input);

    fclose(input);
    return NULL;
}

Фактически вы можете пойти дальше, чем это: если вы открыли каналы в процессе main() перед запуском потоков, вы могли быпросто передайте пару переменных FILE *input и FILE *output в функции потока, что позволит вам использовать одну и ту же функцию потока (с разными параметрами) для каждого потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...