我很难理解文件描述符以及如何从一个文件描述符中读取数据、处理它然后发送到另一个文件描述符。
作为服务器,我需要能够接受连接、接收数据、处理数据,然后将其传递给另一个客户端。
昨天我被介绍了 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
events
现在应该包含可以使用 for 循环遍历的可用 fd 的数量。这就是我从手册中理解的。
一旦我收到其中一个消息,我希望能够处理它(即读取它的内容并做出决定)并最终触发对另一个套接字的写入。
我这样做是为了避免多线程。这是可以实现的吗?
问题是“你想写给哪一个?”
假设您有两个客户端套接字,那么很容易,在 socket_fd1 上读取(或 recv()),在 socket_fd2 上写入(或 send())。就这么简单。
在 C 中,没有什么要求您“回复”客户
您是否需要回复客户端(或另一个)与您要实现的协议/应用程序有关。
随着更多套接字打开,唯一的问题是“数据去哪儿了?”。
您甚至可以将相同的数据发送到所有客户端套接字。将 fds 保存在 table/list/whatsoever 中,并为每个条目 "fd" 调用 send(fd, buf, size, flags);
(听起来您正在尝试编写一种聊天服务,因此您将发送给除接收者之外的所有人:)
如果选择要发送给谁更复杂,请使用包含每个客户更多信息的结构表来做出决定。
希望能解决您的问题。
可能是您没有充分区分:
文件描述符(fd),以及
插座。
你提到“networkfds”。我猜它们是临界的,就像 NFS 文件在某些情况下可能是特殊的。它不是一个文件,而是一个 NFS 文件。
重要的是,因为有状态的 TCP 协议,轮询 fd 是套接字不需要的。(如果我更确定的话,我会加粗。)
一个原始的 UDP 套接字对类似于一对 fd:连接已准备好,但是如何组织数据流呢?解释“互联网”协议 TCP 的普遍性(IP 只是下面的一层,更静态,也很重要。参见维基百科!)。
所以你的设计是愚蠢的吗?根据定义,是的,有点原始。与 TCP/IP 相比。文件描述符是 IO 流的单一联系人,套接字是互联网时代的豪华插头。有
connect
等仅用于套接字。这对你有意义吗?我半路可以跟随你的Q,希望我不会太远。请告诉。
好了朋友们。对于我的问题,我得出了一个结论:这取决于。
这取决于应用程序。我研究了一些仅用于 epoll only/multithread only/ epoll with worker threads 的基准。
我得出的结论是,我将为我的项目使用带有工作线程的 epoll,因为这最有意义:
epoll_wait
当 fd 可用于读/写时,它是最快的 fd 检查器/选择器,但实际工作(解码/分析和处理数据有同时完成(即,与线程)