使用管道的 C 多线程聊天程序

Multithreaded Chat Program in C using Pipes

对于 class 作业,我需要开发一个程序,当在两个单独的 windows 中打开时 - 允许用户在一个 window 上键入并让输入的文本显示在另一个 window 上,而另一个 window 也可以输入并使他们的文本显示在第一个 window 上。

这首先是使用两个单独的程序实现的,一个从 stdin 读取输入,将其写入管道,在管道上调用 fflush,然后从管道获取数据并将其放入 stdout,然后在 stdout 上调用 fflush ,而另一个基本上完全相反。

我来这里是因为我正在努力使单一程序版本工作,我不确定我是否正确理解线程。

这是我的主要功能:

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;
}

但我认为它会阻止第二个程序执行任何操作,因为第一个管道首先连接,并且在第一个程序解锁之前无法完成,这在程序终止之前不会发生。不用说,我很困惑并且很确定我的大部分逻辑都已关闭,但是我无法找到关于在两个不同的控制台 windows 中使用两个线程 运行 两个不同的函数的示例或解释(除非我以某种方式完全误解了赋值,它只是一个函数 运行ning 两次,但我认为情况并非如此)。我将不胜感激一些帮助修复这个程序,以便我可以用它作为一个例子来理解线程在做什么,或者只是解释我将如何实现线程以及为什么。我知道这可能非常简单,但我在这个概念上遇到了麻烦。提前致谢。

如果想法是 my.pipe 用于从第一个程序向第二个程序传输消息,而 my.pipe2 用于向相反方向传输消息,那么看起来这两个程序应该是相同的 除了 交换 my.pipemy.pipe2.

听起来他们希望每个程序有两个线程,一个负责读取第一个管道并写入stdout,另一个负责读取stdin和写入第二个管道。

在这种情况下,你现有的函数看起来是正确的,除了你根本不需要锁 - 它所做的只是立即停止来自 运行 的两个线程,而你的线程'根本不共享任何状态。您的程序的第二个副本将是相同的,除了交换 my.pipemy.pipe2

请注意,您的 InputToPipePipeToOutput 函数包含一个相同的循环,仅在使用的 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 *inputFILE *output线程函数的变量,这将允许您为每个线程使用相同的线程函数(具有不同的参数)。