简体   繁体   English

强制TCP套接字在Java中刷新

[英]Forcing a TCP socket to flush in Java

I'm developing a protocol that requires a handshake that consists of several pieces of information going back and forth in each direction, with several pieces dependent on the previous pieces (think like SSL/TLS handshake). 我正在开发一种协议,需要握手,包括在每个方向上来回传递的几条信息,其中几个部分依赖于之前的部分(想像SSL / TLS握手)。 I'm trying to implement it in Java. 我正在尝试用Java实现它。

A lot of my packets are only 20-30 bytes, whereas my computer seems to think it needs to buffer hundreds of bytes before it sends anything; 我的很多数据包只有20-30个字节,而我的计算机似乎认为它需要在发送任何内容之前缓冲数百个字节; even if I wait 5-10 seconds (with Thread.sleep), it still won't actually send it until I close the socket. 即使我等待5-10秒(使用Thread.sleep),它仍然不会实际发送它,直到我关闭套接字。

How can I get Java/my computer to send what's in its buffer? 如何让Java /我的计算机发送缓冲区中的内容?

On other forums (and SO), a lot of people have been using arguments like "that's not how TCP works", "you shouldn't actually need that." 在其他论坛(和SO)上,很多人一直在使用诸如“那不是TCP的工作方式”这样的论点,“你实际上并不需要这样做。” If I need to send 10 packets each way, each one depends on the last, each one waits for 300ms in the TCP stack, I'm looking at 6s for my handshake, which is completely unusable. 如果我需要每个方向发送10个数据包,每个都依赖于最后一个,每个在TCP堆栈中等待300毫秒,我正在寻找6s用于我的握手,这是完全无法使用的。 (Mind you, I can't get it to send at all, no matter how much I call flush on the socket; I can't get it sent at all until I close the socket). (请注意,我无论如何都无法发送它,无论我在套接字上调用多少刷新;在关闭套接字之前我根本无法发送它)。

I have considered just sending a packet plus enough useless padding to force the TCP implementation to force it, that seems like a bad solution. 我考虑过只发送一个数据包加上足够无用的填充来强制TCP实现强制它,这似乎是一个糟糕的解决方案。

(Simplified, extracted) Code: (简化,摘录)代码:

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);

[I've tried with PrintWriter, OutputStreamWriter; [我尝试过使用PrintWriter,OutputStreamWriter; they don't help.] 他们没有帮助。]

Try this create a simple server : 试试这个创建简单的服务器:

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);
}

Run your client code, but measure the time: 运行您的客户端代码,但测量时间:

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));
}

When I did this I got an output of 15 milliseconds. 当我这样做时,我得到了15毫秒的输出。 This is round trip including both read and write. 这是往返,包括读和写。 If you run this and get something dramatically different, then you probably need to fix something in your network configuration. 如果你运行它并获得一些截然不同的东西,那么你可能需要在网络配置中修复一些东西。 If this gives you about 15 milliseconds you need to look at the difference between this code and your code.The setTcpNoDelay might have an effect but for for me it wasn't noticeable. 如果这给你大约15毫秒,你需要查看这段代码和你的代码之间的区别.setTcpNoDelay可能有效,但对我来说它并不明显。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM