TcpListener的异步调用内存泄漏---最近测试结果,没有泄露
我后来加大了client的连接/断开的次数(500,1000),Server端的连接被释放了。
这说明:
1. 此代码是 可以正常工作的。
2.TcpListener/TcpListener的async的使用上,编译器生成的代码并没有在socket关闭的时候显式调用Disopose(),Dispose()在GC的时候被调用的,个人猜测可能是Pooling,也可能是生成的代码不够漂亮。
--------------------------------------------
最近想写个socket通信的小程序,我相信大凡用过async/await特性的人再也不会去写APM、EAP之类的代码,tcp层的异步通信网上也有很多例子,MSDN上的例子如下: https://msdn.microsoft.com/en-us/magazine/dn605876.aspx , 我参考这个例子写了个Demo,结果发现有内存泄漏,细想应该是某些地方用的不对了,如果有哪位大神看出来,请帮忙指正:
Server端代码:
我们可以看到Tcp上使用TcpListener,并且异步的实现实在NetworkStream上。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace AsyncTcpListenerServer
- {
- using System.IO;
- class Program
- {
- static void Log(string msg)
- {
- Console.WriteLine($"Thread:{Thread.CurrentThread.ManagedThreadId} {msg}");
- }
- static void Main(string[] args)
- {
- ProcessConnectClient();
- Log("Listened success.");
- Console.ReadLine();
- }
- static async void ProcessConnectClient()
- {
- IPAddress ipAddress = IPAddress.Loopback;
- TcpListener listener = new TcpListener(ipAddress, );
- listener.Start();
- Log("Begin start listen...");
- while (true)
- {
- try
- {
- TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
- Log($"listened: {client.Client.RemoteEndPoint}");
- ProcessReceiveData(client);
- }
- catch (Exception ex)
- {
- Console.WriteLine("error:" + ex.ToString());
- }
- }
- }
- static async void ProcessReceiveData(TcpClient client)
- {
- //client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
- IPEndPoint endPoint = (IPEndPoint)client.Client.RemoteEndPoint;
- string info = client.Client.RemoteEndPoint.ToString();
- try
- {
- #region
- //using (NetworkStream networkStream = client.GetStream())
- //{
- // byte[] buffer = new byte[client.ReceiveBufferSize];
- // while (true)
- // {
- // int byteRead = await networkStream.ReadAsync(buffer, 0, client.ReceiveBufferSize).ConfigureAwait(false);
- // if (byteRead <= 0)
- // {
- // break;
- // }
- // Log($" IP:{endPoint.Address} Port:{endPoint.Port} received {byteRead} bytes");
- // }
- //}
- #endregion
- #region MyRegion
- using (NetworkStream networkStream = client.GetStream())
- using (MemoryStream memoryStream = new MemoryStream())
- {
- byte[] buffer = new byte[client.ReceiveBufferSize];
- while (true)
- {
- int byteRead = await networkStream.ReadAsync(buffer, , client.ReceiveBufferSize).ConfigureAwait(false);
- if (byteRead <= )
- {
- break;
- }
- await memoryStream.WriteAsync(buffer, , byteRead).ConfigureAwait(false);
- byte[] bytes = memoryStream.ToArray();
- memoryStream.Seek(, SeekOrigin.Begin);
- string str = Encoding.ASCII.GetString(bytes);
- Log($" IP:{endPoint.Address} Port:{endPoint.Port} {str}");
- }
- }
- #endregion
- #region MyRegion
- //using (NetworkStream networkStream = client.GetStream())
- //using (StreamReader reader = new StreamReader(networkStream))
- //{
- // while (true)
- // {
- // string msg = await reader.ReadLineAsync().ConfigureAwait(false);
- // if (msg == null)
- // {
- // break;
- // }
- // Log($" IP:{endPoint.Address} Port:{endPoint.Port} {msg}");
- // }
- //}
- #endregion
- }
- catch (Exception ex)
- {
- Log(ex.ToString());
- }
- finally
- {
- Console.WriteLine($"client closed!");
- client.Close();
- }
- }
- }
- }
Client端代码:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace AsyncTcpClientClient
- {
- class Program
- {
- static void Main(string[] args)
- {
- Task t = Sending();
- t.Wait();
- Console.WriteLine("OK client");
- }
- static async Task Sending()
- {
- TcpClient client = new TcpClient();
- try
- {
- await client.ConnectAsync(IPAddress.Loopback, );
- using (NetworkStream stream = client.GetStream())
- {
- int i = ;
- while (stream.CanWrite)
- {
- i++;
- if (i>)
- {
- break;
- }
- string msg = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
- byte[] ba = Encoding.Default.GetBytes(msg);
- await stream.WriteAsync(ba, , ba.Length);
- //System.IO.StreamWriter writer = new System.IO.StreamWriter(stream);
- //writer.AutoFlush = true;
- //await writer.WriteLineAsync(msg);
- Console.WriteLine($"Send...{msg}");
- Thread.Sleep();
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- }
- finally
- {
- if (client.Connected)
- {
- client.Close();
- }
- }
- }
- }
- }
写法是特别简单,但是。。。
开启Server端后,运行Client3次端,Server端的显示:
可以看到通信成功,此时抓取Dump,分析结果如下:
Microsoft (R) Windows Debugger Version 10.0.10240.9 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
Loading Dump File [C:\Users\StevenChen\AppData\Local\Temp\AsyncTcpListenerServer (8).DMP]
User Mini Dump File with Full Memory: Only application data is available
WARNING: Minidump contains unknown stream type 0x15
WARNING: Minidump contains unknown stream type 0x16
Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path. *
* Use .symfix to have the debugger choose a symbol path. *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is:
Windows 10 Version 10240 MP (8 procs) Free x64
Product: WinNt, suite: SingleUserTS
Built by: 10.0.10240.16384 (th1.150709-1700)
Machine Name:
Debug session time: Tue Dec 15 17:29:05.000 2015 (UTC + 8:00)
System Uptime: 1 days 8:03:25.088
Process Uptime: 0 days 0:00:49.000
.....................................
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
************* Symbol Loading Error Summary **************
Module name Error
ntdll The system cannot find the file specified
You can troubleshoot most symbol related issues by turning on symbol loading diagnostics (!sym noisy) and repeating the command that caused symbols to be loaded.
You should also verify that your symbol search path (.sympath) is correct.
*** ERROR: Symbol file could not be found. Defaulted to export symbols for KERNELBASE.dll -
ntdll!ZwReadFile+0xa:
00007ff9`313135da c3 ret
0:000> .symfix d:\symbols
0:000> .loadby sos clr
0:000> !fq
No .natvis files found at C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\Visualizers.
c0000005 Exception in C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.fq debugger extension.
PC: 00007ff8`e01b2085 VA: 00000000`00000000 R/W: 0 Parameter: 00000000`00000000
0:000> !fq
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 123 finalizable objects (0000001d743340e0->0000001d743344b8)
generation 1 has 0 finalizable objects (0000001d743340e0->0000001d743340e0)
generation 2 has 0 finalizable objects (0000001d743340e0->0000001d743340e0)
Ready for finalization 0 objects (0000001d743344b8->0000001d743344b8)
Statistics for all finalizable objects (including all objects ready for finalization):
MT Count TotalSize Class Name
00007ff91a6f2ec0 1 32 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
00007ff91a6f2e30 1 32 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
00007ff91a6eab30 1 32 Microsoft.Win32.SafeHandles.SafeWaitHandle
00007ff91a6d1028 1 32 Microsoft.Win32.SafeHandles.SafePEFileHandle
00007ff91a6c1190 1 32 System.Threading.Gen2GcCallback
00007ff91a685878 1 40 System.Threading.RegisteredWaitHandleSafe
00007ff9134adbe8 3 120 System.Net.Sockets.TcpClient
00007ff91a6f0fe8 4 128 Microsoft.Win32.SafeHandles.SafeFileHandle
00007ff91a6d0fc0 2 128 System.Threading.ReaderWriterLock
00007ff91a6d3ff0 2 176 System.Diagnostics.Tracing.EventSource+OverideEventProvider
00007ff91a6ac5e8 1 184 System.Threading.PinnableBufferCacheEventSource
00007ff91a690ab8 1 184 System.Threading.Tasks.TplEtwProvider
00007ff9134ddac8 6 192 System.Net.SafeNativeOverlapped
00007ff9134d5790 3 192 System.Net.Sockets.NetworkStream
00007ff91a6de1e8 2 208 System.IO.FileStream
00007ff9134dda38 6 240 System.Net.SafeCloseSocket
00007ff9134dd820 8 256 System.Net.SafeCloseSocket+InnerSafeCloseSocket
00007ff91a6eee60 3 288 System.Threading.Thread
00007ff91a6d00f8 9 288 Microsoft.Win32.SafeHandles.SafeRegistryHandle
00007ff9134d6aa8 6 288 System.Net.Sockets.OverlappedCache
00007ff91a6e9a20 14 336 System.WeakReference
00007ff9134b60f0 3 528 System.Net.Sockets.AcceptOverlappedAsyncResult
00007ff91a6d3148 21 672 Microsoft.Win32.SafeHandles.SafeAccessTokenHandle
00007ff9134dc7c0 5 680 System.Net.Sockets.Socket
00007ff9134d7368 18 3312 System.Net.Sockets.OverlappedAsyncResult
Total 123 objects
0:000> !dumpheap -mt 00007ff9134dc7c0
Address MT Size
0000001d00034540 00007ff9134dc7c0 136
0000001d00040110 00007ff9134dc7c0 136
0000001d00052de0 00007ff9134dc7c0 136
0000001d000680d8 00007ff9134dc7c0 136
0000001d0007a780 00007ff9134dc7c0 136
Statistics:
MT Count TotalSize Class Name
00007ff9134dc7c0 5 680 System.Net.Sockets.Socket
Total 5 objects
0:000> !gcroot 0000001d00034540
HandleTable:
0000001d71741350 (strong handle)
-> 0000001d0003be08 System.Threading._ThreadPoolWaitOrTimerCallback
-> 0000001d00034540 System.Net.Sockets.Socket
0000001d71741be0 (async pinned handle)
-> 0000001d00052860 System.Threading.OverlappedData
-> 0000001d0007a6d0 System.Net.Sockets.AcceptOverlappedAsyncResult
-> 0000001d00034540 System.Net.Sockets.Socket
Found 2 unique roots (run '!GCRoot -all' to see all roots).
0:000> !gcroot 0000001d00040110
Finalizer Queue:
0000001d00040110
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00040328
-> 0000001d00040328 System.Net.Sockets.TcpClient
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00040c88
-> 0000001d00040c88 System.Net.Sockets.NetworkStream
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00050f20
-> 0000001d00050f20 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00054ba0
-> 0000001d00054ba0 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00054ff8
-> 0000001d00054ff8 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00055450
-> 0000001d00055450 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d000558a8
-> 0000001d000558a8 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
0000001d00055d00
-> 0000001d00055d00 System.Net.Sockets.OverlappedAsyncResult
-> 0000001d00040110 System.Net.Sockets.Socket
Warning: These roots are from finalizable objects that are not yet ready for finalization.
This is to handle the case where objects re-register themselves for finalization.
These roots may be false positives.
Found 9 unique roots (run '!GCRoot -all' to see all roots).
0:000> !dumpheap -mt 00007ff9134d7368
Address MT Size
0000001d00050f20 00007ff9134d7368 184
0000001d00054ba0 00007ff9134d7368 184
0000001d00054ff8 00007ff9134d7368 184
0000001d00055450 00007ff9134d7368 184
0000001d000558a8 00007ff9134d7368 184
0000001d00055d00 00007ff9134d7368 184
0000001d00067c60 00007ff9134d7368 184
0000001d00068a00 00007ff9134d7368 184
0000001d00068e58 00007ff9134d7368 184
0000001d000692b0 00007ff9134d7368 184
0000001d00069708 00007ff9134d7368 184
0000001d00069b60 00007ff9134d7368 184
0000001d0007a308 00007ff9134d7368 184
0000001d0007aea0 00007ff9134d7368 184
0000001d0007b2f8 00007ff9134d7368 184
0000001d0007b750 00007ff9134d7368 184
0000001d0007bba8 00007ff9134d7368 184
0000001d0007c000 00007ff9134d7368 184
Statistics:
MT Count TotalSize Class Name
00007ff9134d7368 18 3312 System.Net.Sockets.OverlappedAsyncResult
Total 18 objects
0:000> !gcroot 0000001d00054ff8
Finalizer Queue:
0000001d00054ff8
-> 0000001d00054ff8 System.Net.Sockets.OverlappedAsyncResult
Warning: These roots are from finalizable objects that are not yet ready for finalization.
This is to handle the case where objects re-register themselves for finalization.
These roots may be false positives.
Found 1 unique roots (run '!GCRoot -all' to see all roots).
我们能够比较明显的看出有些对象没有释放,这些对象的root都指向System.Net.Sockets.OverlappedAsyncResult,但是很奇怪System.Net.Sockets.OverlappedAsyncResult本身也是一个根。
TcpListener的异步调用内存泄漏---最近测试结果,没有泄露的更多相关文章
- Android应用内存泄漏的定位、分析与解决策略
什么是内存泄漏 对于不同的语言平台来说,进行标记回收内存的算法是不一样的,像 Android(Java)则采用 GC-Root 的标记回收算法.下面这张图就展示了 Android 内存的回收管理策略( ...
- 一个跨平台的 C++ 内存泄漏检测器
2004 年 3 月 01 日 内存泄漏对于C/C++程序员来说也可以算作是个永恒的话题了吧.在Windows下,MFC的一个很有用的功能就是能在程序运行结束时报告是否发生了内存泄漏.在Linux下, ...
- Android内存泄漏的检测流程、捕捉以及分析
https://blog.csdn.net/qq_20280683/article/details/77964208 Android内存泄漏的检测流程.捕捉以及分析 简述: 一个APP的性能,重度关乎 ...
- Web 2.0 浏览器端可靠性测试第2部分(如何发现和分析 Web 2.0 浏览器端的内存泄漏)
介绍浏览器端的可靠性测试 在上一编文章中我们介绍了浏览器端可靠性测试的概念.测试方法.以及常用的测试和分析工具.我们知道,浏览器端可靠性测试,就是以浏览器为测试平台,通过模拟用户在真实场景下的页面操作 ...
- Google单元测试框架gtest之官方sample笔记4--事件监控之内存泄漏测试
sample 10 使用event listener监控Water类的创建和销毁.在Water类中,有一个静态变量allocated,创建一次值加一,销毁一次值减一.为了实现这个功能,重载了new和d ...
- 走进异步世界:EnyimMemcached异步化改造引起的内存泄漏
6月30日我们发布了异步化改造后的博客程序之后,出现了高内存.高CPU.高线程数的不理想情况. 经过一周的追查,终于水落日出——引起不理想情况的根源是我们修改过的EnyimMemcached代码存在内 ...
- Qt 内存泄漏测试
在说Qt的内存测试之前,首先需要说明和肯定的一点是:Qt是绝对没有内存泄漏的,我们必须相信这一点. 接下来,说明一下基于Linux的Qt内存测试工具及其用法和说明: 一.内存测试工具Valgrind ...
- WEB页面异步调用场景测试
在我们测试异步调用前,我们首先弄清楚异步调用到底是什么? 异步调用的定义:一个可以无需等待被调用函数的返回值就让操作继续进行的方法, 举一个形象的例子就是:领导给A分配了一个任务, 然后领导就干其他事 ...
- AFNetworking 3.0中调用[AFHTTPSessionManager manager]方法导致内存泄漏的解决办法
在使用AFNetworking3.0框架,使用Instruments检查Leaks时,检测到1000多个内存泄漏的地方,定位到 [AFHTTPSessionManager manager] 语句中,几 ...
随机推荐
- Flask-admin使用经验技巧总结
笔者是看狗书入门的flask,狗书上对于flask-admin这个扩展并没有进行讲解,最近因为项目需要,学习使用flask-admin,瞬间体会到了flask开发的快速.扩展的强大 Flask-adm ...
- BIEE 10g 二次开发整理
近半年在公司做某个项目的时候,主要使用到了Oracle BIEE 10g这套工具.刚开始的时候,对OBIEE是七窍通了六窍,还是一窍不通. 现在已经摸索出些许门道,特整理出来:一来,备忘:二来,供大家 ...
- js数组操作大全(转载)
转载原网址:http://hi.baidu.com/jspboy/item/4923fffb52a28014fe35823a shift:删除原数组第一项,并返回删除元素的值:如果数组为空则返回und ...
- ajax 异步插入图片到数据库(多图上传)
额 大概就这么个样子...截个图 点浏览 选择几张图片 选择完了 确定一下 然后插入数据库 同时在页面中显示插入的图片,代码 也没啥.看下 index.php <html><hea ...
- bat中rar压缩命令
数据库备份,导出的dmp 文件比较大,需要压缩,压缩后大小能变为原来十分之一左右吧. 写的是批处理的语句,每天调用,自动导出dmp 文件,压缩删除原文件. 首先写下路径,先将压缩软件的路径写入系统的环 ...
- wind取交易日历n day数据
days=AlldaysPeriod=Mw.tdaysoffset(5,'20171212','days=Tradingdays;Period=D')
- [原创]VM虚拟机Centos6.4网络配置。
关于虚拟机VMware 3种网络模式(桥接.nat.Host-only)的工作原理http://www.cnblogs.com/hehexiaoxia/p/4042583.html 操作环境 主机:W ...
- linux 硬盘速度测试
[root@iZ25oat874uZ data]# time dd if=/dev/zero of=/var/test bs=8k count=1000000 1000000+0 records in ...
- Solr环境搭建过程中遇到的问题
Solr下载地址:http://www.apache.org/dyn/closer.lua/lucene/solr/6.3.0 Solr搭建步骤转自:http://blog.csdn.net/wbcg ...
- RPN-逆波兰计算器-中缀表达式转后缀表达式-javascript
1.利用栈(Stack)来存储操作数和操作符: 2.包含中缀表达式转后缀表达式的函数,这个是难点,也是关键点: 2.1.将输入字符串转为数组: 2.2.对转换来的字符进行遍历:创建一个数组,用来给存储 ...