我有一个基于异步Socket的长期运行的服务程序。 当其他设备检测到运行状况(短时间TCP端口连接和断开连接)时,其内存使用量会随着时间的推移不断增加。 我怀疑这种类型的TCP连接的内存尚未释放。因此,我编写了一个简单的验证程序:
class Program
{
static void Main(string[] args) => new Program().Start(args[0] == "server");
private void Start(bool bStartServer)
{
if (bStartServer)
{
TcpListener tlToClient = TcpListener.Create(2868);
tlToClient.Start();
DoClientService(tlToClient);
System.Console.WriteLine("start on port 2868...");
for (int i = 0; i < 10; i++)
{
Console.ReadLine();
GC.Collect();
}
}
else
{
for (int i = 0; i < 50000; i++)
{
Socket s = new Socket(SocketType.Stream, ProtocolType.Tcp);
s.Connect("127.0.0.1", 2868);
s.Shutdown(SocketShutdown.Both);
s.Close();
}
System.Console.WriteLine("all done");
Console.ReadLine();
}
}
static async Task DoClientService(TcpListener tlToClient)
{
while (true)
Receive(await tlToClient.AcceptSocketAsync().ConfigureAwait(false));
}
static async Task Receive(Socket socket)
{
while (true)
{
await Task.Delay(50).ConfigureAwait(false);
var read = await socket.ReceiveAsync(new ArraySegment<byte>(new byte[8192], 0, 8192), SocketFlags.None).ConfigureAwait(false);
if (read == 0)
{
socket.Shutdown(SocketShutdown.Both);
socket.Dispose();
return;
}
}
}
}
如代码所示,服务器在端口2868上侦听后,测试客户端将继续启动50,000个TCP连接,连接成功后将关闭这些连接。当服务器接收缓冲区设置为8,192时,测试结束后服务器将占用800MB内存。
我怀疑Socket的扩展方法 ReceiveAsync 的内部实现中存在一个错误,该错误导致无法释放reveive缓冲区。
代码已经简化,只会测试内存泄漏问题。
任何帮助将不胜感激!
答案 0 :(得分:2)
您应该创建一个缓冲区并重用它。垃圾收集不具有侵略性,这可以解释泄漏的原因。更具体地说,此行var Buffer = new ArraySegment<byte>(new byte[8192], 0, 8192);
应该退出while循环,并将其传递到ReciveAsync中。