为了账号安全,请及时绑定邮箱和手机立即绑定

Java NIO 从一个套接字读取并写入另一个套接字的固有缺陷?

Java NIO 从一个套接字读取并写入另一个套接字的固有缺陷?

白猪掌柜的 2021-12-18 09:44:05
我正在研究一个基本的最小服务器概念,使用 NIO 和套接字通道将数据从一个端口传输到另一个目的地。事情在全速、快速链接等情况下运行良好。当一方比另一方快时,事情会非常失败并消耗大量 CPU。事情有效,只是工作效率低下。例子:Iterator keys = selector.selectedKeys().iterator();while (keys.hasNext()) {    SelectionKey key = (SelectionKey) keys.next();    keys.remove();    try {        if (!key.isValid()) continue;        if (key.isReadable()) read(key);    }    catch (Exception e) {        e.printStackTrace();        key.cancel();    }}只要套接字有可以读取的数据,就会调用读取。但是,如果由于客户端具有高延迟或只是没有快速读取数据而无法写入此套接字的可写部分怎么办?我们最终以疯狂的速度循环,直到释放更多可写缓冲区为止:public void read(SelectionKey key) throws IOException {    ByteBuffer b = (ByteBuffer) buffers.get(readable); //prior buffer that may or may not have been fully used from the prior write attempt    int bytes_read = readable.read(b);    b.flip();    if (bytes_read > 0 || b.position() > 0) writeable.write(b);    b.compact();}所以说我们可以从千兆位的套接字读取,但接收器只能从我们的可写套接字以 100 千位读取......我们可能会在可以写入客户端的每个小数据之间循环一百万次,因为它们只是没有像我们想要的那样快地消耗套接字缓冲区中的数据。如果我用一个线程来做这件事,就不会有问题,因为我们会阻塞写调用。但是对于 NIO,您应该怎么做才能让它跳过已读通知?
查看完整描述

1 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

我想通了这一点。我仍然没有找到指向我这一点的文档,但是在考虑了更多事情之后,我意识到这就是 OP_WRITEABLE 场景的用途。

因此,当可写返回它接受 0 字节时,我取消注册可读通道上的 OP_READ,并在可写通道上注册 OP_WRITEABLE。一旦我被告知它是可写的,我就会换回读/写通道,包括它们现在为删除 OP_WRITEABLE 而注册的内容。

因此,当无法完成写入时,请取消注册触发您尝试写入的读取,并在其上注册写入通知。一旦你得到了,换回注册。

现在一切正常。


查看完整回答
反对 回复 2021-12-18
  • 1 回答
  • 0 关注
  • 104 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号