gpt4 book ai didi

c - 使用具有多个客户端的管道

转载 作者:行者123 更新时间:2023-11-30 17:51:26 24 4
gpt4 key购买 nike

我正在尝试使用 C 语言对群聊系统的服务器端进行编程,而我的 friend 正在对客户端进行编程。对于服务器收到的每个客户端连接,它都会派生一个子进程,以便处理客户端并继续接受任何可能的其他客户端。

服务器需要将所有在线用户(连接的客户端)的列表发送到每个当前连接的客户端,因此我使用了管道。基本上,当创建子进程时,它通过套接字接收来自客户端的信息,并通过管道将这些信息发送到保存所有客户端列表的父进程。每当客户端进行更改(例如开始聊天或断开连接)时,都必须更新此列表。例如,如果客户端断开连接,则子级通过管道向父级发送消息,并且父级对列表进行必要的操作以使其更新。请注意,管道是为每个新连接创建的。

我的问题是,例如,如果我相继收到 3 个连接,并且第二个子级断开连接,则父级不会从管道中读取信息,因为此类父级与第二个子级具有不同的管道。 (请记住,由于已建立第三个连接,因此已创建一个新管道)。我该如何解决这个问题?

我也尝试过创建一个公共(public)管道,但如果我在读/写之前不关闭管道,我会收到一个错误,如果我关闭它们,当第二个客户端连接时,我会收到段错误,因为管道将关闭.

任何帮助将不胜感激,因为我已经搜索了几个小时但没有结果。

谢谢。

最佳答案

父服务器进程知道子进程何时创建,因为它创建了子进程。它可以通过设置 SIGCLD 信号处理程序来判断 child 何时死亡,以便在 child 死亡时收到通知。第 N 个子节点有 N-1 个管道需要关闭——这些管道将通向其他子节点(除非其中一些子节点已经死亡)。父进程关闭其创建的管道的写入端;子进程关闭它继承的管道的读取端(这给它留下了一个到客户端的套接字以及为它与父进程通信而创建的管道的写入端)。

如果您需要知道子进程何时开始与客户端通信,那么您需要通过管道从子进程向父进程发送消息。如何判断 child 何时停止交流并不是那么明显——需要经过多长时间才能宣布 child 再次闲置?

在父级中,您最终会以某种形状或形式进行轮询(select()poll()epoll())在监听套接字和所有读取管道上。当某些事件发生时, parent 会醒来并做出适当的 react 。只要不需要扩展到数千或更多客户端,这就是一个可行的设计。它需要一些小心,特别是在关闭足够的文件描述符时。

你说:

My problem is that if for example I receive 3 connections one after another, and the 2nd child disconnects, the parent is not reading the information from the pipe since such parent has a different pipe from the 2nd child. (Remember that a new pipe has been created because a 3rd connection has been made). How can I go about solving this problem?

父级应该有一个打开的文件描述符数组(打开的管道用于读取各个子级),以及哪个子级(PID)位于管道另一端的指示。当父进程在管道上收到 EOF 时,或者当它收到子进程已死亡的通知时(通过 waitpid() 或相关函数),父进程将关闭管道。轮询机制会告诉您管道何时关闭,至少是间接地(您会被告知文件描述符不会阻塞,然后您会得到 EOF - 读取零字节)。

在您的场景中,父级打开了一个监听套接字,以及 3 个用于通向 3 个子级的管道的读取文件描述符(加上标准输入、输出和错误,可能还有系统日志)。

尽管您可以使用所有子级的单个管道,但处理起来要困难得多。您必须确定消息中的每条消息是哪个 child 编写的,确保该消息是由 child 自动写入的。家长必须能够随时知道要读多少内容,以免感到困惑。单管道的优点是轮询系统调用需要执行的文件描述符操作较少;它还可以无限扩展(不会耗尽文件描述符)。

在这两种情况下,您都不应该遇到核心转储问题。

关于c - 使用具有多个客户端的管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16751920/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com