C#异步TCP套接字:处理缓冲区大小和大量传输

asm*_*smo 4 c# sockets buffer asynchronous tcp

使用阻塞TCP套接字时,我不必指定缓冲区大小.例如:

using (var client = new TcpClient())
{
    client.Connect(ServerIp, ServerPort);

    using (reader = new BinaryReader(client.GetStream()))
    using (writer = new BinaryWriter(client.GetStream()))
    {
        var byteCount = reader.ReadInt32();
        reader.ReadBytes(byteCount);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意远程主机如何发送任意数量的字节.

但是,当使用异步TCP套接字时,我需要创建一个缓冲区,从而硬编码最大大小:

 var buffer = new byte[BufferSize];
 socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, null);
Run Code Online (Sandbox Code Playgroud)

我可以简单地将缓冲区大小设置为1024字节.如果我只需要接收一小块数据,那就行了.但是,如果我需要接收10 MB的序列化对象呢?我可以将缓冲区大小设置为10*1024*1024 ......但是只要应用程序运行,就会浪费10 MB的RAM.这太傻了.

所以,我的问题是:如何使用异步TCP套接字有效地接收大块数据?

Nik*_*sov 5

两个示例不相同 - 您的阻塞代码假定远程端发送要跟随的32位数据长度.如果相同的协议对异步有效 - 只需读取该长度(阻塞或不阻塞),然后分配缓冲区并启动异步IO.

编辑0:

我还要补充一点,分配用户输入的缓冲区,特别是网络输入大小的缓冲区是灾难的收据.一个明显的问题是当客户端请求一个巨大的缓冲区并保持它 - 比如非常缓慢地发送数据 - 并阻止其他分配和/或减慢整个系统时的拒绝服务攻击.

这里的常识是一次接受固定数量的数据并随时解析.这当然会影响您的应用程序级协议设计.