[转]SocketAsyncEventArgs 单机测试成功突破 6W
SocketAsyncEventArgs 单机测试成功突破 6W,59999 还是 100%连接上去的 所以估计最高性能可能达到10W以上
请看图吧 由于页宽不够 不能够全显示不过你可以另存为图片查看
实现原理:
采用 SocketAsyncEventArgs 池 和内存池实现.
代码:
/// <summary> /// 启动 /// </summary> public void Start() { if (isDisposed == true) { throw new ObjectDisposedException("ZYServer is Disposed"); } sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); IPEndPoint myEnd = (String.IsNullOrEmpty(Host)) ? (new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], Port)) : (new IPEndPoint(IPAddress.Parse(Host), Port)); sock.Bind(myEnd); sock.Listen(20); SendTimeout = 1000; ReceiveTimeout = 1000; BuffManagers = new BufferManager(MaxConnectCout * MaxBufferSize, MaxBufferSize); BuffManagers.Inint(); SocketAsynPool = new SocketAsyncEventArgsPool(MaxConnectCout); for (int i = 0; i < MaxConnectCout; i++) { SocketAsyncEventArgs socketasyn = new SocketAsyncEventArgs(); socketasyn.Completed += new EventHandler<SocketAsyncEventArgs>(Asyn_Completed); SocketAsynPool.Push(socketasyn); } Accept(); } void Accept() { if (SocketAsynPool.Count > 0) { SocketAsyncEventArgs sockasyn = SocketAsynPool.Pop(); if (!Sock.AcceptAsync(sockasyn)) { BeginAccep(sockasyn); } } else { LogOutEvent(null, LogType.Error, "The MaxUserCout"); } } void BeginAccep(SocketAsyncEventArgs e) { try { if (e.SocketError == SocketError.Success) { if (this.Connetions != null) if (!this.Connetions(e)) { LogOutEvent(null, LogType.Error, string.Format("The Socket Not Connect {0}", e.AcceptSocket.RemoteEndPoint)); e.AcceptSocket = null; SocketAsynPool.Push(e); return; } if (BuffManagers.SetBuffer(e)) { if (!e.AcceptSocket.ReceiveAsync(e)) { BeginReceive(e); } } } else { e.AcceptSocket = null; SocketAsynPool.Push(e); LogOutEvent(null, LogType.Error, "Not Accep"); } } finally { Accept(); } } void BeginReceive(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success&&e.BytesTransferred>0) { byte[] data = new byte[e.BytesTransferred]; Array.Copy(e.Buffer, e.Offset, data, 0, data.Length); if (this.BinaryInput != null) this.BinaryInput.BeginInvoke(data, e, RecevieCallBack, BinaryInput); if (!e.AcceptSocket.ReceiveAsync(e)) { BeginReceive(e); } } else { string message=string.Format("User Disconnect :{0}", e.AcceptSocket.RemoteEndPoint.ToString()); LogOutEvent(null, LogType.Error, message); if (MessageInput != null) { MessageInput(message, e, 0); } e.AcceptSocket = null; BuffManagers.FreeBuffer(e); SocketAsynPool.Push(e); if (SocketAsynPool.Count == 1) { Accept(); } } } void RecevieCallBack(IAsyncResult result) { this.BinaryInput.EndInvoke(result); } void Asyn_Completed(object sender, SocketAsyncEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Accept: BeginAccep(e); break; case SocketAsyncOperation.Receive: BeginReceive(e); break; } }
不用问太多 我也不讲 太多 代码是如此的简单
值得说明的是 建议使用 SocketAsyncEventArgs 进行监听的 读取数据包. 因为 这2个地方的 SocketAsyncEventArgs 是同一个,并且内存和 SocketAsyncEventArgs 对象都好回收 好控制
如果使用 SocketAsyncEventArgs 发送数据包那么 SocketAsyncEventArgs 就不好控制了 所以使用传统的异步模式比较好. 而数据包传出使用 异步代理 进行传出以免堵塞 SocketAsyncEventArgs 线程.
MSND 的 SocketAsyncEventArgs 除了SocketAsyncEventArgsPOOL 和内存Manager 其他纯属扯淡.最好别效仿.
源代码下载地址: http://download.csdn.net/source/2653920
博客地址:http://blog.csdn.net/luyikk/article/details/5081133