当我通过 tcp 发送数据包时,它被分成两个数据包

发布于 2024-07-17 14:08:34 字数 672 浏览 11 评论 0原文

我正在用 C# 开发一个应用程序,使用服务器-客户端模型,其中服务器将带有位图的字节数组发送到客户端,客户端将其加载到屏幕中,向服务器发送“OK”,然后服务器发送另一个图像,等等。

图像缓冲区的长度取决于,通常在 60kb 到 90kb 之间,但我发现这并不重要。 如果我将客户端和服务器放在同一台计算机上,使用本地主机,一切正常。 服务器执行 beginSend,客户端执行 endReceive,然后传输整个缓冲区。

但是,我现在正在无线网络中对此进行测试,发生的情况是:

  • 服务器发送图像。
  • 客户端上的回调函数 data_received 被调用,但只有 1460 个字节可供读取(MTU - 为什么?不应该只在 UDP 中?)
  • 客户端上的回调函数 data_received 被再次调用,现在使用缓冲区的其余部分(要么是 1000 字节,要么是 100 kbytes)...

总是这样,收到第一个 1460 字节的数据包,然后第二个数据包包含其余部分。

我可以通过连接收到的两个字节数组来解决这个问题,但这似乎不对。 我什至不知道为什么会发生这种情况。 是不是网络有什么限制? 那么为什么 C# 不等待整个数据传输完毕呢? 我的意思是,它是 TCP,我不应该担心它,对吗?

无论如何,任何帮助都会很棒!
干杯

I am developing an application in C#, using the server-client model, where the server sends a byte array with a bitmap to the client, the client loads it into the screen, sends an "OK" to the server, and the server sends another image, and so on.

The length of the image buffer deppends, usually it is between 60kb and 90kb, but I've seen that it doesn't matter. If I put the client and the server in the same computer, using localhost, everything works fine. The server does beginSend, and the client does endReceive and the whole buffer is transmitted.

However, I am now testing this in a wireless network and what happens is:

  • The server sends the image.
  • The callback function data_received on the client is called, but there are only 1460 bytes to read (MTU - why? shouldn't only be in UDP?)
  • The callback function data_received on the client is called again, now with the rest of the buffer (either it be 1000 bytes or 100 kbytes)...

It's always like this, a first packet with 1460 bytes is received, and then the second packet contains the rest.

I can work around this by joining both byte arrays received, but this doesn't seem right. I'm not even sure why this is happening. Is it some restriction on the network? Why then doesn't C# wait for the whole data to be transmitted? I mean, it's TCP, I shouldn't have to worry about it, right?

Anyway, any help would be great!
Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

何处潇湘 2024-07-24 14:08:34

它是 TCP - 您应该将数据视为。 您不应该关心流如何分解为数据包,也不应该对其做出假设。

如果您需要接收单个数据“块”,最简单的可靠方法就是在其前面加上长度前缀(例如,作为 32 位值)。 您读取长度(请注意,即使这些字节也可以拆分为多个数据包),然后重复读取(无论是同步还是异步),记下每次读取的数量,直到读完所有内容数据。

It's TCP - you should treat the data as a stream. You shouldn't care how the stream is broken up into packets, or make assumptions about it.

If you need to receive a single "block" of data, the simplest way to do that reliably is to prefix it with the length (e.g. as a 32-bit value). You read the length (noting that even those bytes could be split across multiple packets) and then repeatedly read (whether synchronously or asynchronously) taking note of how much you read each time, until you've read all the data.

我们的影子 2024-07-24 14:08:34

阅读 9.2.4

在剖析应用层协议时,您不能假设每个 TCP 数据包只包含一条应用层消息。 一条应用层消息可以被分割成多个TCP数据包。

Have a read of 9.2.4

When dissecting an application layer protocol you cannot assume that each TCP packet contains exactly one application layer message. One application layer message can be split into several TCP packets.

烂人 2024-07-24 14:08:34

添加约翰的答案:

int offset = 0;
int imagesize = 512;
byte[] buffer = new byte[512];

tcpChannel.Read(buffer, offset, imagesize);

adding to John's answer:

int offset = 0;
int imagesize = 512;
byte[] buffer = new byte[512];

tcpChannel.Read(buffer, offset, imagesize);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文