【问题标题】:Win32 API vs Java socket flushing (TCP)Win32 API 与 Java 套接字刷新 (TCP)
【发布时间】:2017-05-14 22:58:19
【问题描述】:

在 Java 中,可以将几个字节(或者许多小于缓冲区大小的字节)写入套接字的输出流,然后刷新它,以防某些字节需要立即发送。在 Win32 API 中,似乎没有任何类型的刷新功能,所以我觉得在这种情况下“刷新”只是用虚拟字节(可能为零)填充缓冲区的其余部分,以强制发送函数,嗯,发送数据。我的问题是,Java(甚至可能是 C#)如何在后台实现这样的事情?也就是说,如果我有一个 Java 套接字与某个地方的 Win32 套接字通信,考虑到需要一些刷新,它们将如何通信?例如,如果要刷新 Java 套接字的缓冲区(在套接字的 OutputStream 上调用 flush),我会在 Win32 端得到什么(通过调用 recv)?反过来呢?我会看到一些填充行为吗? Win32 端是否需要知道 Java 端的缓冲区大小?不相关的东西?

【问题讨论】:

  • 您是否尝试过寻找来源? .Net core 在 github 上完全可用,你可以看到它是如何实现的

标签: java sockets winapi tcp flush


【解决方案1】:

刷新 Java 套接字输出流没有任何作用。刷新 BufferedOutputStream 会做一些事情,但仅限于应用程序端缓冲区。在这两种情况下,除了刷新所暗示的send()write() 之外,都没有涉及系统调用。你正在寻找不存在的东西。

所以我觉得在这种情况下“刷新”只是用虚拟字节(可能为零)填充缓冲区的其余部分......

没有。

【讨论】:

    【解决方案2】:

    首先回想一下 TCP 提供双向字节流。一方面,您将字节写入套接字,而另一端可以从套接字读取它们。无法保证写入 4 个字节是否会导致一个读取调用在另一端获取 4 个字节。它也可以是 2 乘以 2 个字节。它不是数据包或缓冲区,因此“用虚拟字节填充缓冲区的其余部分”似乎是个坏主意,因为另一方最终会收到这些虚拟字节(并解释它们)。

    接下来的问题:
    在所有应用程序的基础上,有 OS 套接字 API,它们为套接字提供写入/发送调用。当您写入操作系统套接字时,正在写入的字节基本上只写入操作系统的套接字发送缓冲区,它们将在某个时间点从那里发送到远程端。这个时间点取决于发送缓冲区的填充状态以及网络上的情况(TCP 窗口、网络拥塞等)。但是您通常不必关心它,操作系统最终会简单地发送数据并且不需要刷新某些东西。操作系统上有一项设置可用于影响发送行为,即 nagle 算法(或 TCP_NODELAY)设置。如果禁用 nagle 算法(NODELAY = true),这意味着操作系统将在写入调用后立即尝试发送数据,并且不会等待来自应用程序的更多数据以发送更少的 IP 数据包。您可以使用它来减少小数据包的延迟,但没有必要这样做,因为操作系统无论如何都会发送数据。所以它不是必需的同花顺的意义上的同花顺。

    对于 Java 方面,我不确定刷新在做什么。可能是 Java OutputStream 有一个内部缓冲区,只有在达到缓冲区中的某个字节阈值或调用刷新时,才通过 write 系统调用将其写入 OS 套接字。或者,flush 存在纯粹是为了满足 OutputStream 基类,并且什么都不做。通过在 Java 端(或存在它的其他平台)使用 flush 并且在本机套接字 API 中不做任何特殊操作,您应该是安全的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      • 2010-10-10
      • 2017-08-10
      • 1970-01-01
      • 2017-03-08
      相关资源
      最近更新 更多