本人用c#上开发了个 NVR 系统,运行在2003 server r2上,要建立大量的链接,但系统现在试运行有17只摄像头,每个摄像头2个连接,有些断了要重试链接。系统大概运行8天就退出,再运行就发现“由于系统缓冲区空间不足或者队列已满,不能进行套接字上的操作 ”,运行iE浏览器都不行。
链接断了程序都会主动关闭。平时也看不到积累很多半链接
请教哪位大侠能提供点思路
链接断了程序都会主动关闭。平时也看不到积累很多半链接
请教哪位大侠能提供点思路
解决方案 »
- C# 关于对windows下别的窗体的操作(message)
- C# Winform Directory.CreateDirectory()如何在D盘新建一个文件夹
- 水晶报表--求解多次分组后的数据操作和动态列组合问题
- 在VS环境中查找和替换时正则表达式的写法
- C#初学者小问题之五——关于CustomValidator和javascript
- VS2005+Team+TabControl+Alignment=Left+标签文字不显示
- 求助:窗体缩至托盘
- 急,急急,在线等!! VCS express 调试不了,如何解决?
- 如何用程序得到framework安装路径
- web页面如何画棒图、饼图之类的东西
- 用BerConverter.Encode进行BER编码怎么做?
- c# 怎么自定义非可视化控件
问题在于系统的socket队列被你占用光了, 我发使用新的socket, 请在控制台使用netstat命令查看系统的socket状态, 不出意外, 大部分肯定是connect或者其他异常状态
异步socket底层的机制其实用的是iocp的原理,至于原理是什么就不多说了,只是iocp内部的内核队列和线程池机制大家都应该知道,一个socket发送或者接受的时候使用到了线程池,那么就意外着对socket内部缓冲区的访问是线程争用的,我们需要对缓冲区进行同步,当然这是操作系统帮我们完成的了。但是,由于.net的托管性质和GC的影响,socket的缓冲区也是放在堆上的,所以GC可能会回收或者移动缓冲区,而在异步发送和接受BeginXXXX方法的时候用的是底层的iocp线程池机制,所以为了保护该缓冲区,.NEt采用了一种机制“Pinned”内存,被标注为“Pinned”的内存是不能够被回收和移动的,但是,如果异步发送或者接受的速度过快,就会造成堆中有很多的被“Pinned”的内存小块,这时候可以说是形成了堆碎片,由于这些小内存块的不可移动性,导致了现在的堆无法分配出较大的内存块,所以在某些情况下就会出现堆内存溢出,也就是楼主说的问题了,这是net2.0的一个问题,3.5已经改进了异步APM的模型了,性能也更好了,至于楼主说的问题可以采用预先分配的缓冲区池来解决,具体MSDN上面有,搜索一下,这里推荐一篇:http://blogs.msdn.com/tess/archive/2006/09/06/742568.aspx》在我的程序中,由于我调用读录像程序中,每次读数据都调用了 pinned
这段程序如下:
private void ClientReadDataCallBack(IntPtr pUserData, IntPtr pStream, int nStreamLen, IntPtr pHead, int nFlags)
{
bool isHasHead = false;
byte[] streamPackage;
byte[] videoHeaderStream = new byte[1]{0};
byte[] videoStream; _CallbackDateTime = DateTime.Now; if (m_dwWriteBytes > 0)
{
if (pHead.ToInt32() > 0)
{
isHasHead = true;
videoHeaderStream = new byte[8];
Marshal.Copy(pHead, videoHeaderStream, 0, 8);
m_dwWriteBytes += 8;
} videoStream = new byte[nStreamLen];
Marshal.Copy(pStream, videoStream, 0, nStreamLen);
m_dwWriteBytes += nStreamLen; if (isHasHead)
{
streamPackage = new byte[8 + nStreamLen];
Array.Copy(videoHeaderStream, 0, streamPackage, 0, 8);
Array.Copy(videoStream, 0, streamPackage, 8, nStreamLen);
ThreadQueueSend(streamPackage, 8 + nStreamLen);
}
else
{
streamPackage = new byte[nStreamLen];
Array.Copy(videoStream, 0, streamPackage, 0, nStreamLen);
ThreadQueueSend(streamPackage, nStreamLen);
}
videoStream = null;
videoHeaderStream = null;
}
else if (nFlags == 1)
{
byte[] szBuff = new byte[4096];
int nRet = 0; GCHandle hSzBuff = GCHandle.Alloc(szBuff,GCHandleType.Pinned);
IntPtr pSzBuff = hSzBuff.AddrOfPinnedObject(); nRet = PlayerExtProc(_realHandle, 128, pSzBuff.ToInt32(), szBuff.Length);
hSzBuff.Free(); if (nRet > 0)
{
m_dwWriteBytes = nRet; if (pHead.ToInt32() > 0)
{
isHasHead = true;
videoHeaderStream = new byte[8];
Marshal.Copy(pHead,videoHeaderStream, 0, 8);
m_dwWriteBytes += 8;
} videoStream = new byte[nStreamLen];
Marshal.Copy(pStream, videoStream, 0, nStreamLen);
m_dwWriteBytes += nStreamLen; if (nRet > 168)
{
_headerBytes = new byte[nRet - 168];
Array.Copy(szBuff, 168, _headerBytes, 0, nRet - 168);
}
/*
if (isHasHead)
{
streamPackage = new byte[nRet + 8 + nStreamLen];
Array.Copy(szBuff, 0, streamPackage, 0, nRet);
Array.Copy(videoHeaderStream, 0, streamPackage, nRet - 1, 8);
Array.Copy(videoStream, 0, streamPackage, nRet + 7, nStreamLen);
ThreadQueueSend(streamPackage, nRet + 8 + nStreamLen);
}
else
{
streamPackage = new byte[nRet + nStreamLen];
Array.Copy(szBuff, 0, streamPackage, 0, nRet);
Array.Copy(videoStream, 0, streamPackage, nRet - 1, nStreamLen);
ThreadQueueSend(streamPackage, nRet + nStreamLen);
}
*/
if (isHasHead)
{
streamPackage = new byte[8 + nStreamLen];
Array.Copy(videoHeaderStream, 0, streamPackage, 0, 8);
Array.Copy(videoStream, 0, streamPackage, 8, nStreamLen);
ThreadQueueSend(streamPackage, 8 + nStreamLen);
}
else
{
streamPackage = new byte[nStreamLen];
Array.Copy(videoStream, 0, streamPackage, 0, nStreamLen);
ThreadQueueSend(streamPackage, nStreamLen);
}
videoHeaderStream = null;
videoStream = null;
}
szBuff = null;
}
}
有于是录像系统,每只录像机一个线程,每次有录像(1秒要调用多次此函数)都会执行此代码,因此很有可能出现堆溢出问题,请高手能否确诊