c - 处理多个 TCP 客户端
问题描述
我正在编写一个简单的 TCP 服务器,尽管进行了很多谷歌搜索,但我还是无法弄清楚我的问题的答案。
我希望我的服务器能够处理多个客户端。
出于性能和简单性的原因,我希望我的服务器是单线程的,并且我用它select()
来处理所有的套接字。
另外,我的协议是基于消息的。消息框架是使用长度前缀完成的。这意味着服务器需要一个缓冲区来重建一个又一个片段的消息片段。
最大消息长度为 64K 字节(尽管我可以将其减少到 256 字节)。
注意:这将在微型嵌入式设备上运行,因此不能选择使用像 ZMQ 这样的消息传递层(内存不足)。
我可以:
有一个缓冲区,但这意味着一旦我开始从客户端套接字接收/重建消息,我会忽略其他客户端套接字,直到完全接收到当前消息。这很容易受到 DOS 攻击:一个客户端发送一个字节一个字节的巨大消息,非常缓慢,会阻塞服务器。
每个客户端套接字有一个缓冲区,然后我的服务器将真正并行。但它不能很好地随着客户数量的增加而扩展。
是否有另一种方法具有两种技术的优点而没有缺点?
我的一个想法是使用套接字缓冲区来存储整个消息。我会使用setsockopt()
和将缓冲区大小设置为 64K SO_RCVBUFSIZ
。
但是我需要recv()
同时使用MSG_WAITALL
and MSG_DONTWAIT
,以便消息在套接字缓冲区中完全可用并且我得到它,或者它还没有完全接收到然后recv()
不会阻塞。但是,这两个选项不能一起使用。
也许我可以用一个recv()
withMSG_PEEK
来读取大小,然后另一个recv()
withMSG_PEEK
来测试是否所有字节都可用,如果是,那么重新做一个recv()
withoutMSG_PEEK
以实际从套接字读取字节?
无论如何,我的印象是这是一个很久以前就必须解决的微不足道的问题。
解决方案
如果你可以同时拥有,为什么不同时使用呢?
- 为“少数”客户提供大型单一缓冲区。
- 在每个客户端的读取之间保持时间,如果您认为存在 DOS 攻击或读取需要很长时间(由于连接速度慢),请将客户端踢走。这里的想法是实现一个时间窗口。
- 如果您处于“黄金时间”,请增加缓冲区(用于更多客户)或分配另一个缓冲区(基于银行)。
- 否则收缩缓冲区。
只需一点管理,您就可以同时为一些客户服务,而不会浪费宝贵的内存。
推荐阅读
- javascript - 最佳实践 JavaScript 重新抛出保留内部异常
- javascript - 如何使用css根据另一个元素的存在来调整元素的宽度
- j - 如何将相同的 fetch x 值应用于结构化数组中的不同单元格
- spring-boot - 在被覆盖的方法中引用构造函数参数时为空
- angular - 如何使用角度表单控件仅将选中的复选框值推送到数组中
- angular - clickMap 事件不返回坐标 | 离子 | 角谷歌地图
- java - 使用 Spring Data 通过辅助表映射递归关系
- r - 如何在管道中重命名 mlr3 任务特征值
- api - 处理请求时出错的 HTTP 代码
- python - Python:将每行中具有多个值的列转换为列标题