使用.Net Socket 的 SocketAsyncEventArgs 方式做服务端进行侦听接受客户端连接,当并发线程数小于50,且连接的客户端(工业设备)较为稳定不会时常断线时,客户端数量达到3万以上均无问题,且CPU及内存使用量都非常小。但是发现以下情况时服务端会出现崩溃:1、 并发线程数超过 50 时,会出现服务端无法接受新的客户端连接。 经过反复实验发现,再次调用 SocketServer.AcceptAsync(args) 方法可以恢复接受连接,所以估计是 .Net Socket 内部处理问题,导致 args.Completed 事件没有产生。2、 连接到到服务端的设备大批量同时掉线时会出现以下异常,该异常无法捕获: System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>未处理的异常</Description><AppDomain>amschannelwin.vshost.exe</AppDomain><Exception><ExceptionType>System.NullReferenceException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>未将对象引用设置到对象的实例。</Message><StackTrace> 在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)</StackTrace><ExceptionString>System.NullReferenceException: 未将对象引用设置到对象的实例。 在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)</ExceptionString></Exception></TraceRecord>3、 某些工业设备可能未严格按照 TCP 协议进行握手、数据传输、断开连接等底层通讯,导致使用 .Net Socket 编写的服务端出现更为严重的错误,该错误也无法进行异常捕获: 检测到 FatalExecutionEngineError
Message: 运行时遇到了错误。此错误的地址为 0x793dfbf0,在线程 0x744 上。错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug。此 bug 的常见来源包括用户对 COM-interop 或 PInvoke 的封送处理错误,这些错误可能会损坏堆栈。 以上是使用 C# 语言开发 Socket 服务器遇到的问题,但是同样的工业设备连接到 C++ 开发的服务器上没有问题,希望能与 C# 开发遇到同样问题的朋友进行交流。
Message: 运行时遇到了错误。此错误的地址为 0x793dfbf0,在线程 0x744 上。错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug。此 bug 的常见来源包括用户对 COM-interop 或 PInvoke 的封送处理错误,这些错误可能会损坏堆栈。 以上是使用 C# 语言开发 Socket 服务器遇到的问题,但是同样的工业设备连接到 C++ 开发的服务器上没有问题,希望能与 C# 开发遇到同样问题的朋友进行交流。
我的问题和你的不一样,是 异步接收 和 发送时,处理时间 和 处理能力没达到要求,比如收1秒数据处理花了1.1秒 或 1.2秒,这样要主动丢数据等处理,判断很麻烦.发送为了效率用异步,不同网络带宽时延下要发送的数据量又不一样,很少能见到有处理复杂socket的例子和经验文章.
2, 没碰到过
3, 设置一下IOControl看看能解决不
你知道 一个计算机的物理和实际连接数的极限是多少吗?你达到3W的时候已经很饱和了,不知道你用了IOCP没有,建议你能使用IOCP或者扩展一台服务器
this.SocketServer.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
this.SocketServer.SendBufferSize = 255;
this.SocketServer.ReceiveBufferSize = 255;
this.SocketServer.Bind(new IPEndPoint(System.Net.IPAddress.Any, 4002));
this.SocketServer.Listen(500);
this.Accept();private void Accept()
{
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += new EventHandler<SocketAsyncEventArgs>(SocketAsyncEventArgs_Completed); try
{
if (this.SocketServer.AcceptAsync(args) == false)
{
this.AcceptCallback(args);
}
}
catch (Exception)
{
this.Accept();
}
}
以上代码未使用栈来存放空闲SocketAsyncEventArgs以达到可复用的目的,发现入栈出栈更加消耗资源消耗时间问题2和问题3 均是在现场环境中出现的,使用模拟软件未出现过此异常,且现场环境中接入的客户端数量仅为2000不到,并且通讯量并不大,服务端压力也很小。怀疑还是 .Net 底层 Socket 处理的问题。
Larry Cleeton是 System.Net 团队的一名软件设计工程师。您可以通过他的博客 blogs.msdn.com/lcleeton 与他取得联系。
Mike Flasko是 System.Net、Winsock 和 Winsock Kernel 团队的项目经理。您可以通过他的博客 blogs.msdn.com/mflasko 与他取得联系。
Amit Paka是 System.Net 团队的一名软件设计工程师。您可以通过他的博客 blogs.msdn.com/amitpaka 与他取得联系。
楼主应该贴一下。
有多少设备连接,数据上报的方式,数据间的间隔,每个包的大小.既然已经用了SocketAsyncEventArgs 为什么还要建这么多的线程。