发送ACK会大大减慢数据传输速度

时间:2018-01-05 14:34:29

标签: java android sockets tcp

意识到TCP校验和实际上是一个非常差的校验和,这促使我在数据块中包含一个额外的校验和(SHA-256)来验证服务器上数据的完整性,如果已损坏,请求数据再次阻止。但是增加ACK会大大降低数据传输速率。在我的情况下(数据通过wifi传输),速度从~90mbps降低到~12mbps。

客户端:

if(values.contains("{")){
        values = values.replaceAll("\\{", "");
    }
    if(values.contains("}")){
        values = values.replaceAll("\\}", "");
    }

服务器:

SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("192.168.31.30", 3333));
ByteBuffer byteBufferData = ByteBuffer.allocateDirect(1024 * 8);
ByteBuffer byteBufferACK = ByteBuffer.allocateDirect(1);
for (int i = 0; i < 1024; i++) {
    // write data (payload + checksum (SHA-256))
    socketChannel.write(byteBufferData);
    byteBufferData.clear();
    // read ACK
    socketChannel.read(byteBufferACK);
    byteBufferACK.clear();
    // if (byteBufferACK.get() == XXX)
        // ... retransmission byteBufferData
}

请注意,该代码是测试代码,并非用于传达任何有用的数据。它仅用于测试数据传输速率。

我有两个问题:

  1. 也许我不理解某些内容或做错了,但为什么发送一个字节的数据作为数据接受(ACK)的确认会影响整体数据传输速率呢?怎么避免这个?
  2. SHA-256是否足以作为8kb大小数据的校验和? (在现有的TCP CRC之上)

1 个答案:

答案 0 :(得分:3)

因为你在等待它。让我们说你和服务器之间有200ms的延迟。如果没有确认,您可以尽快写入数据包,使带宽饱和并停止。使用ack,它看起来像这样:

t=0  send 1st 8k
t=200 server recieves
t=205ish  server sends ack
t=405 client recieves ack.
t=410ish client sends 2nd 8k

您浪费了50%的发送时间。我真的很惊讶它并没有变得更糟。

TCP中有很多功能可以防止出现这些问题,包括滑动数据窗口(你不发送一个数据包并确认它,你发送N个数据包,服务器确认它收到的数据包,允许丢失的数据包无序重新发送)。你很难重新实现TCP,而且几乎肯定不应该。

如果你打算这样做 - 不要使用TCP。使用UDP或原始套接字并在此基础上编写新协议。您仍然使用TCP确认和校验和,因此您的工作是多余的。