java - 强制 TCP 套接字在 Java 中刷新

标签 java sockets tcp

我正在开发一个需要握手的协议(protocol),该握手包含在每个方向上来回传递的几条信息,其中几条信息依赖于之前的信息(类似于 SSL/TLS 握手)。我正在尝试用 Java 实现它。

我的很多数据包只有 20-30 个字节,而我的计算机似乎认为它需要在发送任何内容之前缓冲数百个字节;即使我等待 5-10 秒(使用 Thread.sleep),在我关闭套接字之前它仍然不会真正发送它。

如何让 Java/我的计算机发送其缓冲区中的内容?

在其他论坛(和 SO)上,很多人一直在使用诸如“这不是 TCP 的工作方式”、“你实际上不应该需要它”之类的论点。如果我需要每路发送 10 个数据包,每个都依赖于最后一个,每个都在 TCP 堆栈中等待 300 毫秒,我正在寻找 6 秒的握手时间,这是完全无法使用的。 (请注意,无论我在套接字上调用多少次 flush,我都根本无法发送它;在关闭套接字之前,我根本无法发送它)。

我考虑过只发送一个数据包加上足够多的无用填充来强制 TCP 实现强制它,这似乎是一个糟糕的解决方案。

(简化、提取)代码:

Socket sock = new Socket("localhost", 1234);
OutputStream output = sock.getOutputStream();
output.write(new byte[] {(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef});
output.flush();
Thread.sleep(5000);

[我尝试过使用 PrintWriter、OutputStreamWriter;他们没有帮助。]

最佳答案

尝试创建一个简单的服务器:

public static void main(String[] args) throws IOException {
    ServerSocket svr = new ServerSocket(1234);
    Socket s = svr.accept();
    byte b4[] = new byte[4];
    new DataInputStream(s.getInputStream()).readFully(b4);
    s.getOutputStream().write(b4);
}

运行您的客户端代码,但测量时间:

public static void main(String[] args) throws IOException {
    Socket sock = new Socket("localhost", 1234);
    OutputStream output = sock.getOutputStream();
    long t1 = System.currentTimeMillis();
    output.write(new byte[]{(byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef});
    byte b4[] = new byte[4];
    new DataInputStream(sock.getInputStream()).readFully(b4);
    long t2 = System.currentTimeMillis();
    System.out.println("t2-t1="+(t2-t1));
}

当我这样做时,我得到了 15 毫秒的输出。这是往返,包括读取和写入。如果你运行它并得到一些截然不同的东西,那么你可能需要在你的网络配置中修复一些东西。如果这给您大约 15 毫秒,您需要查看此代码与您的代码之间的区别。setTcpNoDelay 可能会产生影响,但对我来说并不明显。

关于java - 强制 TCP 套接字在 Java 中刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32445734/

相关文章:

networking - 网络数据包中的哪些字段应该转换为网络字节序

java - 为什么JSON发送的数据在表格中显示不正确?

java - 如何从HDF5文件读取属性?

java - 使用RandomAccessFile和多线程时,如何分割大字 rune 件?

java - 如何从 Java 中的套接字获取客户端名称?

java - 如何使用UDP或TCP发送压缩数据(lua/java)

java - 概率数学总是输出零?

c# - 以下方法之间的调用不明确

c - 在两个不同进程之间共享 OpenSSL BIO

javascript - 使用 websocket.send 如何知道消息何时到达?