C# 我应该如何处理不完整的数据包缓冲区?

C# 我应该如何处理不完整的数据包缓冲区?,c#,sockets,buffer,C#,Sockets,Buffer,我正在为服务器编写一个客户端,该服务器通常以500字节或更少字节的字符串形式发送数据。然而,数据偶尔会超过这个值,而且一组数据可能包含200000字节,这是客户端所知道的(在初始化或重大事件时)。但是,我不想让每个客户机都运行一个50MB的套接字缓冲区(如果可能的话) 每组数据由空\0字符分隔。对于存储部分发送的数据集,我应该考虑什么样的结构 例如,服务器可能会发送ABCDEFGHIJKLMNOPQRSTUV\0WXYZ\0123\0。我想处理ABCDEFGHIJKLMNOPQRSTUV,WXY

我正在为服务器编写一个客户端,该服务器通常以500字节或更少字节的字符串形式发送数据。然而,数据偶尔会超过这个值,而且一组数据可能包含200000字节,这是客户端所知道的(在初始化或重大事件时)。但是,我不想让每个客户机都运行一个50MB的套接字缓冲区(如果可能的话)

每组数据由空
\0
字符分隔。对于存储部分发送的数据集,我应该考虑什么样的结构

例如,服务器可能会发送
ABCDEFGHIJKLMNOPQRSTUV\0WXYZ\0123\0
。我想处理
ABCDEFGHIJKLMNOPQRSTUV
WXYZ
123独立。此外,服务器可以发送
abcdefghijklmnopqrstuvxyz1234567890lol123hahahathisisreallyllong
,而不使用终止字符。我希望将该数据集存储在某个地方,以便以后进行附加和处理

此外,我正在使用异步套接字方法(
BeginSend
EndSend
BeginReceive
EndReceive
),如果这很重要的话


目前我正在讨论
List
StringBuilder
。在这种情况下,对两者进行任何比较都会非常有帮助。

将数据从套接字读取到缓冲区中。当您获得终止字符时,将其转换为消息并将其发送到代码的其余部分

另外,请记住,TCP是一个流,而不是一个数据包。因此,您永远不应该假设您将在一次读取中同时发送所有内容

就缓冲区而言,每个连接最多只需要一个缓冲区。我可能会从您合理期望接收的最大大小开始,如果这个最大大小已满,则创建一个更大的新缓冲区-一个典型的策略是在用完时将大小加倍,以避免过多分配


如果有多个传入连接,您可能需要创建一个缓冲池,并在处理完缓冲池后将“大”的缓冲池返回到缓冲池中。

我只需要使用一个缓冲池,一次读取一个字符,每当我遇到空终止符时,就复制并清空构建器。

我写了这个关于Java套接字的答案,但概念是一样的


您可以使用
列表作为缓冲区,因此.NET framework会根据需要自动扩展它。当您找到空终止符时,可以使用
List.RemoveRange()
从缓冲区中删除该消息并将其传递到上一层

您可能希望添加一个检查,并在异常超过一定长度时抛出异常,而不是等到客户机内存耗尽


(这与Ben的答案非常相似,但我认为字节数组在编码问题上比StringBuilder更健壮。一旦你有了完整的信息,将字节解码为字符串最好在更高层进行。)

这就是我的想法,但我担心这会是一个效率杀手。它不应该是,它被设计用来有效地处理附加任意字符串。可能是
内存流
,而不是
列表
?和
stream.Seek(0,SeekOrigin.Begin)
而不是
RemoveRange
。这也是一种可能性。我想这取决于代码的结构。如果它在遇到空终止符后立即处理消息,则查找0将正常工作。但是,如果它首先读取所有挂起的套接字数据,然后查找空终止符,则在第一条消息之后,查找0将丢失所有内容。我假设是后者。