C#网络流碎片数据

Ent*_*ity 0 c# networkstream fragment beginread

我的背景

我有一个TCP网络程序,它通过连接发送已经序列化并编码到base64的大对象.我写了一个客户端库和一个服务器库,他们都使用NetworkStream's Begin/EndReadBegin/EndWrite.这是我正在使用的代码(非常简化的版本):

对于服务器:

var Server = new TcpServer(/* network stuffs */);
Server.Connect();
Server.OnClientConnect += new ClientConnectEventHandler(Server_OnClientConnect);

void Server_OnClientConnect()
{
    LargeObject obj = CalculateLotsOfBoringStuff();
    Server.Write(obj.SerializeAndEncodeBase64());
}
Run Code Online (Sandbox Code Playgroud)

然后客户:

var Client = new TcpClient(/* more network stuffs */);
Client.Connect();
Client.OnMessageFromServer += new MessageEventHandler(Client_OnMessageFromServer);

void Client_OnMessageFromServer(MessageEventArgs mea)
{
    DoSomethingWithLargeObject(mea.Data.DecodeBase64AndDeserialize());
}
Run Code Online (Sandbox Code Playgroud)

客户端库有一个回调方法,NetworkStream.BeginRead用于触发OnMessageFromServer将数据作为字符串传递的事件MessageEventArgs.

我的问题

BeginRead/EndRead但是,当通过它接收大量数据时,它似乎在多个消息上分散.EG假装这是一条很长的信息:

"This is a really long message except not because it's for explanatory purposes."
Run Code Online (Sandbox Code Playgroud)

如果这确实是一个很长的消息,Client_OnMessageFromServer可能会被称为...说"三条消息"的碎片部分:

"This is a really long messa"

"ge except not because it's for explanatory purpos"

"es."
Run Code Online (Sandbox Code Playgroud)

Soooooooo ...... 深吸一口气

通过Begin/EndWrite一次通话接收所有内容的最佳方式是什么Client_OnMessageFromServer

Mar*_*ell 6

你不能.在TCP上,事物的到达方式不一定与发送方式相同.您的代码的工作是知道什么构成完整的消息,并且如果有必要缓冲传入的数据,直到您完整的消息(注意不要丢弃下一个消息的开始我的过程).

在文本协议中,这通常意味着"发现换行符/ nul-char".对于二进制,它通常意味着"读取消息的前导码中的长度标题".