使用阻塞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套接字有效地接收大块数据?
答案 0 :(得分:5)
两个示例不相同 - 您的阻塞代码假定远程端发送要跟随的32位数据长度。如果相同的协议对异步有效 - 只需读取该长度(阻塞或不阻塞),然后分配缓冲区并启动异步IO。
我还要补充一点,分配用户输入的缓冲区,特别是网络输入大小的缓冲区是灾难的收据。一个明显的问题是denial-of-service攻击,当客户端请求一个巨大的缓冲区并保持它 - 比如非常缓慢地发送数据 - 并阻止其他分配和/或减慢整个系统。
这里的常识是一次接受固定数量的数据并随时解析。这当然会影响您的应用程序级协议设计。