我们可以用阻塞套接字制作一个非阻塞服务器吗?

标签 c sockets unix select

我必须为我的 IT 学校制作一个简单的 IRC 客户端/服务器程序。主题要求我们使用 select(2) 进行套接字轮询,但禁止我们使用 O_NONBLOCK 套接字。

  • Your server will accept multiple simultaneous connections.
    Attention, the use of fork is prohibited. So you should imperatively use select
  • Your server must not be blocking.
    This has nothing to do with non-blocking sockets, which are prohibited (so do not use fcntl(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/

相关文章:

c - 比 printk() 更好的方法来留下内核模块日志?

c++ - 在使用 fwrite 创建图像后交换字节

c - 宏编译

linux x86 tcp bind shellcode(GAS语法)bind()不返回零

regex - Shell 脚本 - sed 不起作用

python - 通过转义必要的东西将 shell 脚本转换为一个衬里?

c - 为什么递归函数调用需要返回一个值给调用函数?

C++ 套接字发送/接收与写入/读取

java - 区分 "out of range"或 "in range, but no listening server socket"? (蓝牙)

shell - 如何查找 PWD 中引用 PWD 之外的文件的所有符号链接(symbolic link)? UNIX