socket异步接收,内存持续增大

sgchen 2014-06-17 05:33:47
我自己封装了一个tcpclient类,采用异步接收的方式,测试时开1000个连接发数据,发现内存一直在增大。

/// <summary>
/// 连接,一般用于客户端的创建
/// </summary>
/// <param name="ServerIP">Socket连接的IP地址</param>
/// <param name="Port">Socket连接的端口</param>
public void Connect(string ip, int port)
{
ConnectByParams(ip, port, DEFAULT_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
}
private void ConnectByParams(string ip, int port, int sendBufferSize, int receiveBufferSize)
{
_connIp = ip;
_connPort = port;
try
{
_SendBufferSize = sendBufferSize;
_ReceiveBufferSize = receiveBufferSize;
_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Socket.SendBufferSize = _SendBufferSize;
_Socket.ReceiveBufferSize = _ReceiveBufferSize;
_Socket.NoDelay = true;
_ReceiveBuffer = new byte[_Socket.ReceiveBufferSize];
_Socket.BeginConnect(ip, port, new AsyncCallback(ConnectCallBack), _Socket);
}
catch (Exception ex)
{
if (ExceptionEvent != null)
ExceptionEvent(this, new SocketEventArgs(null, "连接失败:" + ex.Message));
this.Close();
}
}
private void ConnectCallBack(IAsyncResult iar)
{
try
{
iar.AsyncWaitHandle.Close();

if (!IsConnected)
throw new Exception("");
if (SocketConnectedEvent != null)
SocketConnectedEvent(this, true);
_Socket.BeginReceive(_ReceiveBuffer, 0, _ReceiveBuffer.Length, SocketFlags.None, acRcv, _Socket);
}
catch (Exception ex)
{
if (SocketConnectedEvent != null)
SocketConnectedEvent(this, false);
if (ExceptionEvent != null)
ExceptionEvent(this, new SocketEventArgs(null, "连接失败:" + ex.Message));
this.Close();
}
}

/// <summary>
/// 接收数据
/// </summary>
private void AsynRecvCallBack(IAsyncResult iar)
{
if (_Socket == null) return; //防止其他线程关闭Socket;
try
{
int nLen = _Socket.EndReceive(iar);
iar.AsyncWaitHandle.Close();

if (nLen <= 0) //使用接收0字节作为远端Socket断开的判断
{
if (SocketDisconnectedEvent != null)
SocketDisconnectedEvent(this, null);
this.Close();
}
else
{
byte[] m_ByteDatas = new byte[nLen];
Array.Copy(_ReceiveBuffer, 0, m_ByteDatas, 0, nLen);
if (ReceivedEvent != null)
ReceivedEvent(this, new SocketEventArgs(m_ByteDatas, null));

//继续接收
_Socket.BeginReceive(_ReceiveBuffer, 0, _ReceiveBuffer.Length, SocketFlags.None, acRcv, null);
}
}
catch (SocketException ex)
{
if (ExceptionEvent != null)
ExceptionEvent(this, new SocketEventArgs(null, "Type:" + ex.GetType().Name + ";ErrorCode:" + ex.ErrorCode.ToString() + ";Msg:" + ex.Message +
"\r\n" + ex.StackTrace));

if (ex.ErrorCode != 10035)
{
if (SocketDisconnectedEvent != null)
SocketDisconnectedEvent(this, null);
this.Close();
}
}
catch (Exception ex)
{
if (ExceptionEvent != null)
ExceptionEvent(this, new SocketEventArgs(null, ex.GetType().Name + ":" + ex.Message + "\r\n" + ex.StackTrace));
}
}

查了很多地方都没发现哪里提到过异步接收会有这个问题,尝试增加iar.AsyncWaitHandle.Close();也无效;

byte[] m_ByteDatas = new byte[nLen];
Array.Copy(_ReceiveBuffer, 0, m_ByteDatas, 0, nLen);
if (ReceivedEvent != null)
ReceivedEvent(this, new SocketEventArgs(m_ByteDatas, null));
这一段注释掉也不行。

奇了怪了,哪位大侠碰到过类似的问题,求解....
...全文
994 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamlilinfeng 2016-10-21
  • 打赏
  • 举报
回复
这个问题我也遇到了。上面说的方法都不是根本问题,代码看都来都对,但就是内存在增大。我们是要找出哪些对象被挂起即:GC回收不了。 解决方案:使用:.NET Memory Profiler 4.0工具查看大对象的调用堆栈。找出根本原因并解决。
大强快跑 2015-03-01
  • 打赏
  • 举报
回复
我也碰到这样的问题,感觉是网络带宽不够造成的,还没有找到解决的办法。
dengshushu68 2014-07-09
  • 打赏
  • 举报
回复
楼主,你的问题解决了吗? 我的公司,家里电脑都这样哦。。 这里有篇文章说这样可以解决,但是我拿下来,用他原带代码及修改后的测试都还是会持续增加。 http://blog.csdn.net/ani/article/details/7182035
bdmh 2014-06-18
  • 打赏
  • 举报
回复
new了大量的缓存,又得不到及时的释放
sgchen 2014-06-18
  • 打赏
  • 举报
回复
最奇怪是就是我的公司电脑是这样,试了其他人的同样的系统也不会出现内存一直增长的问题
sgchen 2014-06-18
  • 打赏
  • 举报
回复
引用 13 楼 ZIP_xG 的回复:
[quote=引用 12 楼 sgchen2000 的回复:] [quote=引用 11 楼 ZIP_xG 的回复:] 主动调用垃圾释放看看 如果调用后大幅下降就不用管了,.Net会自动处理的
试过家GC.Collect(),不管用[/quote] 你copy出去的byte[]拿来干什么了? 主要原因是你引发事件的byte[]没有释放造成的[/quote] 前面说过了,即使注释掉 byte[] m_ByteDatas = new byte[nLen]; Array.Copy(_ReceiveBuffer, 0, m_ByteDatas, 0, nLen); if (ReceivedEvent != null) ReceivedEvent(this, new SocketEventArgs(m_ByteDatas, null)); 也是一样
Kation 2014-06-18
  • 打赏
  • 举报
回复
引用 12 楼 sgchen2000 的回复:
[quote=引用 11 楼 ZIP_xG 的回复:] 主动调用垃圾释放看看 如果调用后大幅下降就不用管了,.Net会自动处理的
试过家GC.Collect(),不管用[/quote] 你copy出去的byte[]拿来干什么了? 主要原因是你引发事件的byte[]没有释放造成的
sgchen 2014-06-18
  • 打赏
  • 举报
回复
引用 11 楼 ZIP_xG 的回复:
主动调用垃圾释放看看 如果调用后大幅下降就不用管了,.Net会自动处理的
试过家GC.Collect(),不管用
Kation 2014-06-18
  • 打赏
  • 举报
回复
主动调用垃圾释放看看 如果调用后大幅下降就不用管了,.Net会自动处理的
sgchen 2014-06-18
  • 打赏
  • 举报
回复
引用 8 楼 tcmakebest 的回复:
1000个能测出什么问题,请用10万个来测,再看使用的内存数量,如果是线性上涨那才是有问题.
1000个已经发现问题了,因为是持续接收数据,所以很明显看见每次不断增大,以1000条/秒的频率发数据,半小时左右程序的内存就达到500M了。
嘿呀土豆 2014-06-18
  • 打赏
  • 举报
回复
不能光接收用完要释放的嘛!!
tcmakebest 2014-06-18
  • 打赏
  • 举报
回复
1000个能测出什么问题,请用10万个来测,再看使用的内存数量,如果是线性上涨那才是有问题.
sgchen 2014-06-18
  • 打赏
  • 举报
回复
引用 6 楼 SwingingMace 的回复:
[quote=引用 4 楼 sgchen2000 的回复:] [quote=引用 2 楼 SwingingMace 的回复:] 1、测试不发不收,只连接。 2、测试只发不收。 3、测试只收不发。 这样可以判断是收发的问题,还是收与发哪一个出了问题。
确实这样试了,是收数据造成的。[/quote] 每收一次就清空一次buff了吗?[/quote] 我是这样写的: _Socket.BeginReceive(_ReceiveBuffer, 0, _ReceiveBuffer.Length, SocketFlags.None, acRcv, null); _ReceiveBuffer是局部变量,每次都是用这个,还有必要清空吗?
SwingingMace 2014-06-18
  • 打赏
  • 举报
回复
引用 4 楼 sgchen2000 的回复:
[quote=引用 2 楼 SwingingMace 的回复:] 1、测试不发不收,只连接。 2、测试只发不收。 3、测试只收不发。 这样可以判断是收发的问题,还是收与发哪一个出了问题。
确实这样试了,是收数据造成的。[/quote] 每收一次就清空一次buff了吗?
sgchen 2014-06-18
  • 打赏
  • 举报
回复
很奇怪的是,我在公司的机子上试是这种状况,拿回家试又没有问题。 家里装的是windows7 sp1 64位,公司是windows7 sp1 32位。 我有在windows2008下测试也没有问题。 我在公司的机子上尝试用.net framework 4.5,也是同样的结果。 真不明白系统哪个地方会导致这种现象。
sgchen 2014-06-18
  • 打赏
  • 举报
回复
引用 2 楼 SwingingMace 的回复:
1、测试不发不收,只连接。 2、测试只发不收。 3、测试只收不发。 这样可以判断是收发的问题,还是收与发哪一个出了问题。
确实这样试了,是收数据造成的。
SwingingMace 2014-06-18
  • 打赏
  • 举报
回复
1、测试不发不收,只连接。 2、测试只发不收。 3、测试只收不发。 这样可以判断是收发的问题,还是收与发哪一个出了问题。
wangnaisheng 2014-06-17
  • 打赏
  • 举报
回复
.dispose() 释放资源试试
《Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket上发送数据 4.6.2 在“无连接的”socket上发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T

110,529

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧