gpt4 book ai didi

java - 在不知道长度的情况下从 TcpClient.GetStream() 读取

转载 作者:行者123 更新时间:2023-12-01 09:32:05 25 4
gpt4 key购买 nike

我正在研究基于 TCP 的通信协议(protocol)。我所知有很多方法可以确定何时结束阅读。

  1. 在消息结束时关闭连接
  2. 将消息长度放在数据本身之前
  3. 使用分隔符;一些在普通数据中永远不会出现的值(或者总是会以某种方式转义)
<小时/>

通常我会尝试通过 WiFi 网络发送文件(可能不稳定且速度较低)

  • RSA 和 AES 通信的原因我不喜欢每次都关闭连接(无法使用 1)
  • 这是一个很大的文件,我无法预测它的长度,所以我无法采取行动as 方法(不能使用 2)
  • 读取时检查特殊内容并写入时转义需要大量过程(不能使用 3)
  • 此方法应与 c# 和 java 兼容。

你有什么建议?

<小时/>

更一般的问题:

How to identify end of InputStream in java

C# - TcpClient - Detecting end of stream?

更多信息

我正在编写 TCP 客户端服务器通信

首先服务器生成并向客户端发送 RSA 公共(public)代码。

然后客户端将生成 AES(key,IV) 并使用 RSA 加密将其发回。

到这里一切都很好。

但我想通过该网络发送文件。这是我当前的数据包 EncryptUsingAES(new AES.IV(16 byte) +file.content(any size))

在服务器中,我无法捕获客户端发送的所有数据。所以我需要知道要读取多少数据 (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);

最佳答案

你的第二种方法是最好的方法。在每个数据包前面加上数据包长度前缀将创建一个可靠的消息帧协议(protocol),如果正确完成,将确保所有数据都被接收,即使其大小与发送数据的大小相同(即,没有部分数据或数据被集中在一起)。

  • 推荐的数据包结构:

    [Data length (4 bytes)][Header (1 byte)][Data (?? bytes)]

    - 所讨论的 header 是一个字节,您可以使用它来指示这是什么类型的数据包,以便端点知道如何处理它。


发送文件

在 90% 的情况下,文件的发送者知道将要发送的数据量(毕竟,文件通常存储在本地),这意味着知道有多少文件已发送或未发送是没有问题的。

我使用和推荐的方法是首先发送一个“信息包”,它向端点解释它将接收一个文件以及该文件包含多少字节。之后,您开始发送实际数据 - 最好以 block 的形式发送,因为一次处理整个文件的效率很低(至少如果它是一个大文件)。

  • 始终跟踪到目前为止您已收到的文件字节数。通过这样做,接收者可以自动判断何时收到了整个文件。
  • 一次发送几千字节的文件(我使用 8192 字节 = 8 kB 作为文件缓冲区)。这样您就不必将整个文件读入内存,也不必同时对其进行加密。


加密数据

处理加密不会有问题。如果您使用长度前缀,只需加密数据本身并保持数据长度 header 不变。然后,数据长度 header 必须由加密数据的大小生成,如下所示:

  1. 加密数据。
  2. 获取加密数据的长度。
  3. 生成以下数据包:

    [Encrypted data length][Encrypted data]

    (如果需要,请在其中插入 header 字节)


接收加密文件

接收加密文件并知道何时收到所有内容实际上并不难。假设您使用上述方法发送文件,您只需:

  1. 接收加密数据包→解密。
  2. 获取解密数据的长度。
  3. 增加一个变量来跟踪接收到的文件字节数。
  4. 如果收到的金额等于预期金额:关闭文件。


其他资源/引用

您可以引用我之前写的关于 TCP 长度前缀消息帧的两个答案:

关于java - 在不知道长度的情况下从 TcpClient.GetStream() 读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39321771/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com