Win32 API 与 Java 套接字刷新 (TCP)

Win32 API vs Java socket flushing (TCP)

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

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

so I feel like "flushing" in this case is just padding the rest of the buffer with dummy bytes (probably zeroes) ...

没有

首先回忆一下,TCP 提供双向字节流。一方面,您将字节写入套接字,另一方面可以从套接字读取它们。无法保证写入 4 个字节是否会导致一次读取调用在另一端获取 4 个字节。它也可以是 2 乘以 2 字节。它没有数据包或缓冲区,因此 "padding the rest of the buffer with dummy bytes" 似乎是个坏主意,因为另一方最终会收到这些虚拟字节(并解释它们为任何内容)。

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

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