我必须为我的 IT 学校制作一个简单的 IRC 客户端/服务器程序。主题要求我们使用 select(2)
进行套接字轮询,但禁止我们使用 O_NONBLOCK
套接字。
- Your server will accept multiple simultaneous connections.
Attention, the use offork
is prohibited. So you should imperatively useselect
- Your server must not be blocking.
This has nothing to do with non-blocking sockets, which are prohibited (so do not usefcntl(s, O_NONBLOCK)
)
我想知道是否有可能设计一个带有阻塞套接字的非阻塞服务器(不 fork ),即使使用select(2)
。
这是一个简单的例子:假设我们有一个简单的文本协议(protocol),每行一个命令。每个客户端都有一个缓冲区。当 select(2)
告诉我们客户端已准备好 read(2)
时,我们会一直读取,直到在客户端缓冲区中找到 \n
,因此我们处理该命令。对于非阻塞套接字,我们将读取直到 EAGAIN
。
现在假设我们正在使用阻塞套接字,并且恶意客户端发送没有换行符的文本。 select(2)
告诉我们数据可用,然后我们在客户端上read(2)
。但我们永远不会读取预期的 \n
。系统调用将无限期地阻塞,而不是返回 EAGAIN。这是拒绝服务攻击。
真的有可能设计一个带有阻塞套接字和select(2)
(没有fork(2)
)的非阻塞服务器吗?
最佳答案
是的,您从套接字读取一次,select
告诉您已准备好。如果 read
包含 \n
,则处理该行。否则,存储接收到的所有数据,并立即返回到选择
。
这当然意味着,对于每个打开的套接字,您必须维护状态信息以及迄今为止读取的数据缓冲区。这允许代码独立处理每个读取
,无需在返回select
之前完成整行。
关于我们可以用阻塞套接字制作一个非阻塞服务器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29246511/