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

时间:2019-03-03 05:38:43

标签: c multithreading pthreads chat

对于班级作业,我需要开发一个程序,该程序-在两个单独的窗口中打开时-允许用户在一个窗口中键入并在另一个窗口中显示输入的文本,而另一个窗口也可以键入并将其文本显示在第一个窗口中

这首先使用两个独立的程序实现,一个程序从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;
}

但是相反,我认为它会阻止第二个程序执行任何操作,因为先连接了第一个管道,并且只有在第一个程序将其解锁后才能执行此操作,而在第一个程序终止之前不会发生。不用说,我很困惑,并且可以肯定地说,我的大多数逻辑都是关闭的,但是我无法找到有关在两个不同的控制台窗口中使用两个线程来运行两个不同功能的示例或说明(除非我完全以某种方式误解了分配,并且它只是一个函数运行两次,但是我不认为是这种情况。我将不胜感激,或者可以通过一些帮助修复该程序的方式来使我作为示例来了解线程在做什么,或者仅对如何实现线程及其原因进行解释。我知道这可能很简单,但是我在概念上遇到了麻烦。预先感谢。

1 个答案:

答案 0 :(得分:1)

如果想法是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变量传递给线程函数,这样您就可以为每个线程使用相同的线程函数(具有不同的参数)。