gpt4 book ai didi

c# - 使用 Begin* End* 方法时,在 C# 中处理数据包碎片的工作示例是什么样的?

转载 作者:行者123 更新时间:2023-11-30 22:49:27 24 4
gpt4 key购买 nike

在玩够了异步套接字编程之后,我注意到服务器正在接收分块的有效载荷(即:多个完整的有效载荷位于同一缓冲区中)。所以我想出了以下办法:

if (bytes_to_read > 0)
{
while (bytes_to_read > 0)

// Get payload size as int.

// Get payload in byte format.

// Do something with payload.

// Decrease the amount of bytes to read.
}

// Wait for more data.
}

然后我注意到数据包碎片(即:我认为是完整的负载组合在一起的东西并不总是这样),这将之前的代码更改为类似:

if (bytes_to_read > 0)
{
while (bytes_to_read > 0)
{
// Get payload size as int.

// Check if the payload size is less than or equal to the amount of bytes left to read.
if (payload_size <= bytes_to_read)
{
// Get payload in byte format.

// Do something with payload.

// Decrease the amount of bytes to read.
}
else
{
// We received a fragmented payload.
break;
}
}

if (bytes_to_read == 0)
{
// Wait for more data.
}
else if (bytes_to_read > 0)
{
// Wait for more data where we left off. ***
}
else
{
// Something awful happened.
}
}

*** 我什至不知道该怎么做,想看看它的代码。我有一个想法,它涉及将未完成的有效负载复制到缓冲区的开头,然后从那里获取。

我包含的伪代码基于我正在使用的 Begin* End* 方法(我知道我应该使用此处找到的 *Async 方法集 -> http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx <- 但我认为我的整体问题仍然适用)。

我正在寻找 2 个问题的答案——即:

  1. 这种方法是否正确,或者我缺少什么?
  2. 什么是工作示例处理数据包碎片C# 长什么样?

编辑:我正在使用原始套接字。

预先感谢您的所有帮助。

编辑:约翰·桑德斯 (John Saunders) 和格雷格·休吉尔 (Greg Hewgill) 提出了将数据视为流的观点,但这并没有为我提供一个具体示例来说明如何处理有时被分段的最后一个分块负载。

编辑:我已阅读 Jon Skeet 的回答 here这基本上与我看到的其他答案相同,但它对我没有太大帮助,因为我已经知道我必须做什么,但不知道如何去做。

编辑:为了详细说明我所说的碎片化的意思,请考虑以下接收缓冲区:

  • 224TEST3foo3bar
  • 224TEST3foo3bar224TEST3foo3bar
  • 224TEST3foo3bar224TEST3foo
  • 3bar224TEST3foo3bar

编辑:我找到了 thisthis这引导我here . Vadym Stetsiak几乎清除了所有内容(他是我一直在寻找的答案之一)。

最佳答案

这可能与碎片化有关,也可能无关。

一般来说,socket 一次会传递尽可能多的字节给你。您的工作是了解整个消息中有多少字节,然后全部读取。一直循环直到您拥有所需的所有字节,或者直到出现异常。


以下代码目前未经测试。我想我会先发布它,然后再编写它的服务器端并测试两者。

private static string ReceiveMessage(Socket socket)
{
const int BUFFER_SIZE = 1024;
var inputBuffer = new byte[BUFFER_SIZE];
var offset = 0;
var bytesReceived = socket.Receive(
inputBuffer, offset, BUFFER_SIZE - offset, SocketFlags.None);
if (bytesReceived < 2)
{
throw new InvalidOperationException("Receive error");
}

var inputMessageLength = inputBuffer[0]*256 + inputBuffer[1];
offset += bytesReceived;
var totalBytesReceived = bytesReceived;
while (bytesReceived > 0 &&
totalBytesReceived < inputMessageLength + 2)
{
bytesReceived = socket.Receive(
inputBuffer, offset, BUFFER_SIZE - offset, SocketFlags.None);
offset += bytesReceived;
totalBytesReceived += bytesReceived;
}

return Encoding.UTF8.GetString(
inputBuffer, 2, totalBytesReceived - 2);
}

注意收到的消息长度是错误的。套接字层可以一次给我一个字节。作为重构的一部分,我将重新审视它,将计数接收到一个单独的两字节缓冲区,并将循环更改为单个 do/while。

关于c# - 使用 Begin* End* 方法时,在 C# 中处理数据包碎片的工作示例是什么样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1129000/

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