【问题标题】:Non-blocking socket writes in Java versus blocking socket writesJava 中的非阻塞套接字写入与阻塞套接字写入
【发布时间】:2011-11-10 21:57:57
【问题描述】:

为什么有人更喜欢阻塞写入而不是非阻塞写入?我的理解是,如果您想确保在写入方法返回后对方收到 TCP 数据包,您只会想要阻止写入,但我什至不确定这是否可能。您将不得不刷新并且刷新将不得不刷新底层操作系统写入套接字缓冲区。那么非阻塞套接字写入有什么缺点吗?就性能而言,拥有一个大的底层写入套接字缓冲区是不是一个坏主意?我的理解是,底层套接字写入缓冲区越小,您就越有可能遇到缓慢/错误的客户端,并且当底层套接字缓冲区已满且 isWritable() 返回 false 时,您必须在应用程序级别丢弃/排队数据包。

【问题讨论】:

    标签: java sockets networking tcp nio


    【解决方案1】:

    我的理解是,如果你想确保一旦写入方法返回,另一端就收到了 TCP 数据包,你只会想要阻止写入

    你的理解不正确。它不能确保这一点。

    阻塞写入阻塞,直到所有数据都传输到套接字发送缓冲区,从那里异步传输到网络。如果阅读器速度慢,他的socket接收缓冲区会填满,最终会导致你的socket发送缓冲区填满,这会导致一个阻塞写入阻塞,阻塞整个线程。非阻塞 I/O 为您提供了一种检测和处理这种情况的方法。

    【讨论】:

    • 所以简而言之:阻塞写入会阻塞,非阻塞写入可以使用 isWritable() 调用来确定底层套接字写入缓冲区是否已满,并决定在不阻塞的情况下做什么。所以我的问题的(危险)答案是:非阻塞写入比阻塞写入更好。您拥有更多控制权和相同的性能。
    • @achrisapotek 准确地说,isWritable() 意味着最后一次 select() 在 OP_WRITE 事件上触发,此时套接字发送缓冲区中有空间。您的问题的答案是非阻塞写入不会阻塞。这是否更好取决于您的需求。
    • 如果在触发 OP_WRITE 时有空间,当 isWritable() 稍后在循环中返回 true 时,您将有空间。除非有另一个线程编写没有什么意义。我很难想象阻塞写入更可取的情况。当然,您总是可以想出一个,但非阻塞写入让您可以选择决定做什么:等待(阻塞)、排队数据包、丢弃数据包或终止客户端。那好多了!!!
    • @chrisapotek。 (1) 缓冲区中有空间 (2) OP_WRITE 触发了 select() (3) isWritable() 返回 true (4) 你进入了那个循环 (5) 第一次写入填充了套接字发送缓冲区 (5) 还有更多数据留在 ByteBuffer 所以(6)你再次迭代循环,写入返回零,与(5)相同数量的数据仍然存在,所以(7)你再次迭代循环......阻塞的情况当您每个客户端都有一个线程时,写入更可取。
    【解决方案2】:

    非阻塞写入的问题是,如果写入不完整,您可能没有任何有用的事情可做。你可以结束像

    这样的循环
    // non-blocking write
    while(bb.remaining() > 0) sc.write(bb);
    

    // blocking write
    sc.write(bb);
    

    第一个可以烧CPU,第二个可能更可取。

    最大的问题是读取。一旦您决定是要阻塞还是非阻塞读取,您的写入必须相同。不幸的是,没有办法让它们与众不同。如果你想要非阻塞读,你必须有非阻塞写。

    【讨论】:

    • select()OP_WRITE 是“无事可做”的解决方案。
    • 使用选择器进行非阻塞写入可能更有效。但是恕我直言,它应该是如此罕见,这可能并不重要。
    • @EJP:当底层写入套接字缓冲区已满并且您已注册 OP_WRITE 时,即使认为 isWritable() 将返回 false,选择器是否选择可写键,将自己置于像彼得一样的循环中说?或者当缓冲区中的空间可用时选择键是否足够聪明?
    • @chrisapotek 这在术语上完全是矛盾的。 select() 返回 OP_WRITE 意味着套接字发送缓冲区中有空间。没有别的了。
    • @EJP:所以彼得描述的循环不会发生,因为不会在完整缓冲区的情况下选择键。如果你调用 isWritable() 并且它返回 true,你就可以写了,否则你必须排队或放弃,你决定。
    猜你喜欢
    • 2013-02-23
    • 1970-01-01
    • 2011-10-09
    • 2010-10-31
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    相关资源
    最近更新 更多