我正在尝试编写一个聊天程序,协议是 TCP,两个文件是 server.c 和 client.c,如果客户端和客户端是通过 fork 创建的并且具有相同的套接字描述符,那么如何从客户端向客户端发送消息。没有...
我正在尝试编写一个聊天程序,协议是 TCP,两个文件是 server.c 和 client.c如果它们是通过 fork 创建的并且具有相同的套接字描述符,则如何从客户端向客户端发送消息。
无论我如何尝试发送消息,它都会出现在发送消息的同一控制台窗口中
问题是,无论何时 fork()
,创建的子进程都是一个独立的进程,具有自己的私有内存空间和单独的文件描述符表。它将继承其父进程的文件描述符,但此后,父进程中稍后创建的任何文件描述符都将在(已经存在的)子进程中不可用。
这意味着,例如,如果您的服务器接收到第一个 TCP 连接并创建文件描述符 123 来表示它,并分叉一个子进程来处理它,然后接收到第二个 TCP 连接,创建文件描述符 124 来表示它,并分叉第二个子进程来处理它,则第一个子进程将根本无法使用文件描述符 124,因为该文件描述符从未添加到其文件描述符表中。
如果您想让子进程向其他子进程发送数据,最好的办法是让子进程将数据发送给父进程,然后让父进程将该数据转发给所有其他子进程。但请注意,这并非易事,因为您需要通过每个子进程的标准输入/标准输出文件描述符传递这些数据,或者使用或类似方法设置与每个子进程的连接 socketpair()
。
如果您想避免所有这些复杂情况,最好生成线程而不是分叉子进程,因为这样所有线程至少都可以访问所有文件描述符(因为它们都在同一内存空间中一起执行)。但是,您需要处理锁定/同步/所有权问题,以确保所有这些线程都能安全地访问文件描述符。
第三种选择是使用非阻塞 I/O 和 select()
/或 poll()
多路复用 I/O 操作在单个线程中执行所有服务器操作。这是我通常默认的做法,因为尽管实现起来有点复杂,但根据我的经验,它仍然是三种方法中最容易 100% 正确的方法。