我很难理解文件描述符以及如何从一个文件描述符读取数据、处理它然后发送到另一个文件描述符。
作为服务器,我需要能够接受连接、接收数据、处理数据,然后将其传递给另一个客户端。
昨天我已经了解了 epolling,我想知道我的策略对于创建客户端-服务器网络是否正确。
创建了一个 epollfd。我将其指定为边沿触发 (EPOLLET) 和非阻塞(使用:flags |= 0_NONBLOCK
和 fctnl(epollfd, F_SETFL, flags)
.
我的目的是现在创建一个networkfds(客户端套接字)数组并监听连接/消息。
- 收到有关新数据的通知
- 读取数据
- 处理数据
- 将一些数据写入另一个套接字。
我在 linux man 和 online 中找到的所有示例仅提供有关如何从套接字读取数据的信息,如果我尝试让许多客户端同时与许多客户端进行通信,我担心我的设计很愚蠢并且会失败。
我决定在这里问,因为我读到NGINX(网络服务器正在使用epolling)
有人可以帮忙吗?
编辑1:我打算在列表(struct epoll_event *events)中有(许多)套接字并通过epoll_wait()访问它们。
// If I understand correctly:
int ndfs = epoll_wait(epollfd, events, MAX_EVENTS, -1);
// Puts some events in the <events> array and an int in ndfs
nfds
现在应该包含可用 fd 的数量,events
可以在其中使用 for 循环进行迭代。这是我从手册中了解到的。
一旦我收到来自其中一个的消息,我希望能够处理它(即读取其内容并做出决定)并最终触发对另一个套接字的写入。
我这样做是为了避免多线程。这是可以实现的吗?
答案1
问题是“你想写给哪一位?”
假设您有两个客户端套接字,那么很容易,在socket_fd1上读取(或recv()),并在socket_fd2上写入(或send())。就这么简单。
在 C 中,没有什么要求你“回复”客户端
您是否需要回复客户端(或另一个客户端)与您要实现的协议/应用程序有关。
随着更多的套接字打开,唯一的问题是“数据去哪里?”。
您甚至可以将相同的数据发送到所有客户端套接字。将 fd 保存在表/列表/任何内容中,并为每个条目“fd”调用 send(fd, buf, size, flags);
(听起来您正在尝试编写一种聊天服务,因此您将发送给除您收到的服务之外的所有人:)
如果选择要发送给谁比较复杂,请使用包含每个客户更多信息的结构表来做出决定。
希望能解决您的问题。
答案2
您可能没有充分区分:
文件描述符(fd),以及
插座。
你提到“networkfds”。我猜它们是边界性的,就像 NFS 文件在某些情况下可能很特殊一样。它不是一个文件,而是一个 NFS 文件。
这很重要,因为,据我所知,由于有状态 TCP 协议,套接字不需要轮询 fd。 (如果我更确定的话,我会加粗这一点。)
原始 UDP 套接字对类似于一对 fd:连接已准备好,但如何组织数据流?解释了“互联网”协议 TCP 的普遍性(IP 只是下面的一层,更静态,也很重要。请参阅维基百科!)。
那么你的设计是愚蠢的吗?根据定义,是的,有点原始。与 TCP/IP 相比。文件描述符是 IO 流的单一触点,套接字是互联网时代的豪华插头。有connect
等仅适用于套接字。
这对你来说有意义吗?我一半可以遵循你的问题,希望我不会离得太远。请告诉。
答案3
好了朋友们。我对我的问题得出了一个结论:这要看情况。
这取决于应用程序。我学仅 epoll/仅多线程/带工作线程的 epoll 的一些基准。
我的结论是,我将在我的项目中使用 epoll 和工作线程,因为这最有意义:epoll_wait
当 fd 可用于读/写时,它是最快的 fd 检查器/选择器,但实际工作(解码/分析和处理数据)并发完成(即使用线程)