在周期性调用的循环中通过TCP发送的第一个请求需要很长时间

时间:2015-11-13 22:26:08

标签: java sockets tcp

我遇到了我怀疑是TCP的行为,我不理解,并希望得到帮助。

定期调用通过TCP发送请求并读取响应的循环。

无论循环的大小如何,发送的第一个请求 - 响应对几乎总是比其他对花费更多的时间。

当我在同一台机器上运行客户端和服务器时,这不会发生,因此我怀疑这与TCP有关。

下面的代码示例说明了问题:

每秒调用一次:

    for (int sentPackets = 0; sentPackets < totalPackets; sentPackets++) {

        // send request
        stream.write(packet);
        stream.flush();             
        long sentAt = System.currentTimeMillis();

        // read response
        String response = StreamReader.read(inputStream, buffer);
        long receivedAt = System.currentTimeMillis();

        long dif = receivedAt - sentAt;

        System.out.println("dif: "+ dif);

StreamReader可用于从套接字读取。

读取方法实现如下所示:

public static String read(DataInputStream stream, byte[] buffer) throws IOException {

    int totalBytes = 0;

    // keep reading from stream until entire packet is available
    while (totalBytes < buffer.length) {

        // read into buffer, from position of latest byte read, up to size of buffer
        int bytesRead = stream.read(buffer, totalBytes, buffer.length - totalBytes);

        // premature end of stream
        if (bytesRead == -1) {

            System.out.println("unexpected end of stream during socket read operation");
            break;
        }

        else
            totalBytes = bytesRead;
    }

    return new String(buffer);
}

时间戳之间没有其他操作,只能写入和读取套接字。

在循环之间的那一秒会发生什么导致这种行为在localhost上不会发生?

Bellow是可视化的一些例子。

dif: 172
dif: 15
dif: 0
dif: 0

dif: 0
dif: 0
dif: 0
dif: 0

dif: 203
dif: 0
dif: 16
dif: 0

dif: 47
dif: 0
dif: 0
dif: 16

dif: 16
dif: 16
dif: 0
dif: 0

1 个答案:

答案 0 :(得分:1)

我怀疑Nagle's algorithm

  Nagle的算法以John Nagle的名字命名,是一种通过减少需要通过网络发送的数据包数量来提高TCP / IP网络效率的方法。它通过组合一些小的外发消息并一次性发送它们来工作。

对Windows上的localhost禁用Nagle算法(但不禁用Mac或Linux)。

如果延迟确实存在问题,您可以使用TCP_NODELAY套接字选项禁用Nagle算法。如果您发送大量小数据包,它将以更高带宽为代价减少延迟。