意识到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
}
请注意,该代码是测试代码,并非用于传达任何有用的数据。它仅用于测试数据传输速率。
我有两个问题:
答案 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确认和校验和,因此您的工作是多余的。