使用管道的 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.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
线程函数的变量,这将允许您为每个线程使用相同的线程函数(具有不同的参数)。
对于 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.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
线程函数的变量,这将允许您为每个线程使用相同的线程函数(具有不同的参数)。