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

时间:2011-04-10 03:28:16

标签: c# sockets asynchronous tcp buffer

使用阻塞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);
    }
}

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

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

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

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

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

1 个答案:

答案 0 :(得分:5)

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

编辑0:

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

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