我正在研究tcp基础通信协议。我所知 有很多方法可以确定何时结束阅读。
通常我试图通过WiFi网络发送文件(可能是不稳定和低速)
你的建议是什么?
更一般的问题:
How to identify end of InputStream in java
C# - TcpClient - Detecting end of stream?
更多信息
我正在编写TCP客户端服务器通信
首先,服务器生成并向客户端发送RSA公共代码。
然后客户端将生成AES(密钥,IV)并使用RSA加密将其发回。
直到这里一切都很好。
但我想通过这个网络发送文件。这是我当前的数据包EncryptUsingAES(新的AES.IV(16字节)+ file.content(任何大小))
在服务器中,我无法捕获客户端发送的所有数据。所以我需要知道要读取多少数据(TcpClient.GetStream()。read(buffer,0,buffersize)) 目前的代码:
List<byte> message = new List<byte>();
int bytes = -1;
do
{
byte[] buffer = new byte[bufferrSize];
bytes = stream.Read(buffer, 0, bufferrSize);
if (bytes > 0)
{
byte[] tmp = new byte[bytes];
Array.Copy(buffer, tmp, bytes);
message.AddRange(tmp);
}
} while (bytes == bufferrSize);
答案 0 :(得分:1)
你的第二种方法是最好的方法。使用数据包的长度为每个数据包添加前缀将创建一个可靠的消息成帧协议,如果正确完成,即使与您发送的数据相同,也可以确保收到所有数据(即,没有部分数据或数据存在集中在一起)。
推荐的数据包结构:
[Data length (4 bytes)][Header (1 byte)][Data (?? bytes)]
- 有问题的标题是一个单字节,您可以用它来指示这是什么类型的数据包,以便端点知道如何处理它。
文件的发件人在90%的情况下知道它将要发送的数据量(毕竟,它通常将文件存储在本地),这意味着知道已经发送了多少文件就没问题了。
我使用和推荐的方法是首先发送一个&#34; info数据包&#34;,它向端点解释它即将接收文件以及该文件包含多少字节。之后,您开始发送实际数据 - 最优选的是块,因为一次性处理整个文件效率很低(至少如果它是一个大文件)。
处理加密不会有问题。如果使用长度前缀,则只加密数据本身并保持数据长度标头不变。然后必须根据加密数据的大小生成数据长度标题,如下所示:
生成以下数据包:
[Encrypted data length][Encrypted data]
(如果需要,在那里插入标题字节)
接收加密文件并知道何时收到所有内容实际上并不是很难。假设您使用上述方法发送文件,您只需:
你可以参考我之前写的关于TCP长度前缀消息框架的两个答案:
答案 1 :(得分:0)
最简单的方法是使用你的#2。如果你无法预测消息长度,请缓冲一定数量的字节(如1 KiB或这些行中的某些内容),并为每个块插入一个长度标头,而不是为整个消息添加一次。