【问题标题】:Does Java's TCP Socket class block when sending dataJava的TCP Socket类在发送数据时会阻塞吗
【发布时间】:2011-07-05 11:09:49
【问题描述】:

当我使用 Javaa 的 Socket 类发送一个字节数组时,以下代码中的 write 调用是否会阻塞,直到它验证接收者已收到数据?

byte data[] = ...;
Socket socket = ...;

socket.getOutputStream().write(data); // blocking ?

我问的原因是,如果我有一个要发送相同数据的套接字列表,我想尽可能高效地发送它,即,有没有比这更好的方法:

ArrayList<Socket> sockets = ...;
byte data[] = ...;

for(int i = 0; i < sockets.size(); i++)
  sockets.getOutputStream().write(data);

【问题讨论】:

    标签: java sockets tcp blocking


    【解决方案1】:

    TCP 握手发生在connect(2) 时间,而不是write(2) 时间。

    write(2) 的调用将被阻塞,直到操作系统 TCP 发送缓冲区耗尽足以从程序接收更多数据。 (我无法想象操作系统会为单个空闲字节解锁 write(2) 操作。)

    唯一的保证是客户端在过去已经接受了数据,并且不超过会话的 TCP 窗口大小加上内部操作系统缓冲区的大小。无论是否有任何数据到达另一端点上的应用程序,都是另一层缓冲区——远程对等端上的 TCP 堆栈将确认接收到的数据并将其存储在应用程序之前的缓冲区中有机会处理它。

    【讨论】:

    • 所以你是说一旦数据到达栈的tcp层就会解除阻塞,不用等到与客户端的整个tcp握手完成?
    • @gamemb,直到握手完成后,您的代码才会继续调用write()。 (每个会话在connect() 时间握手一次。)但是,是的,当 local TCP 发送缓冲区已释放足够的空间来接受 write() 调用时,代码将解除阻塞——这可能比远程对等方接收到的和ACKed 提前 64KB 窗口 + 8KB 缓冲区大小。
    • (请注意,64KB 窗口只是一个猜测——使用TCP window scaling,窗口可能是兆字节大,几乎高达一千兆字节的数据。但需要专门的环境才能拥有一千兆字节传输中的数据。:)
    • 是的,我知道。那么,请记住,是否有更好的方法将相同的数据发送给多个客户端,就像上面的简单循环一样?
    • @gamernb,两种可能的方法是(a)每个 TCP 会话使用一个线程,这样阻塞只会影响一个线程/连接,而不是阻止所有数据传输的进度(b)使用 Java 的Selector 将数据写入准备接受写入的套接字的工具。 (这对应于 C select(3) 函数。)如果您尝试几乎同时向客户端发送同步的游戏数据,这可能是一个更好的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多