当使用阻塞 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 套接字有效地接收大块数据?
两个示例并不等效 - 您的阻塞代码假设远程端发送了后续数据的 32 位长度。如果相同的协议对异步有效 - 只需读取该长度(是否阻塞),然后分配缓冲区并启动异步 IO。
Edit 0:
我还要补充一点,分配用户输入的缓冲区,尤其是网络输入的缓冲区大小,会带来灾难。一个明显的问题是拒绝服务 http://en.wikipedia.org/wiki/Denial_of_service当客户端请求一个巨大的缓冲区并保留它时(比如发送数据非常缓慢)并阻止其他分配和/或减慢整个系统时,就会发生攻击。
这里的常识是一次接受固定数量的数据并进行解析。这当然会影响您的应用程序级协议设计。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)