强制TCP套接字在Java中刷新

时间:2015-09-07 20:36:40

标签: java sockets tcp

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

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

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

在其他论坛(和SO)上,很多人一直在使用诸如“这不是TCP如何工作”这样的论点,“你实际上并不需要这样做。”如果我需要每个方向发送10个数据包,每个都依赖于最后一个,每个在TCP堆栈中等待300毫秒,我正在寻找6s用于我的握手,这是完全无法使用的。 (请注意,我无法将它发送到任何地方,无论我多少次在套接字上调用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;他们没有帮助。]

1 个答案:

答案 0 :(得分:1)

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

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可能有效,但对我来说它并不明显。