SocketAsyncEventArgs 单机测试成功突破 6W (转)
http://blog.csdn.net/luyikk/article/details/5081133
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
又问题可以联系我 luyi@5173.com