C# IOCPServer 异步I/O模型
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using LinFx.Net;
using LinFx.Win32;
namespace LinFx.Net.Server
{
/// <summary>
/// 异步I/O模型
/// </summary>
public class IOCPServer : IDisposable
{
private IntPtr m_hWnd;
private Socket m_sListen;
private System.Collections.ArrayList m_Clients = new System.Collections.ArrayList();
private readonly AsyncCallback onAccepted;
private readonly AsyncCallback onReceived;
private readonly AsyncCallback onSend;
public IOCPServer()
{
onAccepted = new AsyncCallback(ListenEndAccept);
onReceived = new AsyncCallback(ClientEndRecv);
onSend = new AsyncCallback(ClientEndSend);
}
public IOCPServer(IntPtr handle)
: this()
{
this.m_hWnd = handle;
}
public void Run()
{
new Thread(new ThreadStart(ListenThreadMethod)).Start();
}
/// <summary>
///
/// </summary>
private void ListenThreadMethod()
{
IPAddress ip = IPAddress.Parse("222.222.222.187");
IPEndPoint ipe = new IPEndPoint(ip, 1234);
m_sListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_sListen.Bind(ipe);
m_sListen.Listen(50);
//预先投递 Accept 请求
for (int i = 0; i < 5; i++)
{
PostAccept();
}
}
#region CallBack
/// <summary>
/// 请求 callback
/// </summary>
/// <param name="asyncResult"></param>
private void ListenEndAccept(IAsyncResult asyncResult)
{
//投递一个 Accept 请求
PostAccept();
AsyncState state = asyncResult.AsyncState as AsyncState;
Socket socket = state.socket.EndAccept(asyncResult);
lock (this.m_Clients.SyncRoot)
{
this.m_Clients.Add(socket);
}
//投递一个接收请求
PostRecv(socket);
}
/// <summary>
/// 接收 callback
/// </summary>
/// <param name="asyncResult"></param>
private void ClientEndRecv(IAsyncResult asyncResult)
{
AsyncState state = asyncResult.AsyncState as AsyncState;
int recvSize = state.socket.EndReceive(asyncResult);
//远端连接已关闭
if (recvSize == 0)
{
lock (this.m_Clients.SyncRoot)
{
this.m_Clients.Remove(state.socket);
}
return;
}
//再投递一个接收请求
PostRecv(state.socket);
//将收到的数据发送回去
PostSend(state.buffer, state.offset, state.size, state.socket);
}
/// <summary>
/// 发送 callback
/// </summary>
/// <param name="asyncResult"></param>
private void ClientEndSend(IAsyncResult asyncResult)
{
AsyncState state = asyncResult.AsyncState as AsyncState;
byte[] buffer = state.buffer;
int sentBytes = state.socket.EndSend(asyncResult);
int remainBytes = state.size - sentBytes;
if (remainBytes <= 0)
return;
System.Diagnostics.Debug.WriteLine(string.Format("Buffer length: {0} Remain bytes: {1} Sent bytes: {2}", buffer.Length, remainBytes, sentBytes));
PostSend(buffer, buffer.Length - remainBytes, remainBytes, state.socket);
}
#endregion
#region 投递重叠 I/O
/// <summary>
/// 投递接受 I/O
/// </summary>
private void PostAccept()
{
m_sListen.BeginAccept(0, onAccepted, new AsyncState(m_sListen));
}
/// <summary>
/// 接收 I/O
/// </summary>
/// <param name="socket"></param>
private void PostRecv(Socket socket)
{
byte[] buffer = new byte[1024];
socket.BeginReceive(buffer,
0,
buffer.Length,
SocketFlags.None,
onReceived,
new AsyncState(buffer, 0, buffer.Length, socket));
}
/// <summary>
/// 发送 I/O
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <param name="socket"></param>
private void PostSend(byte[] buffer, int offset, int size, Socket socket)
{
socket.BeginSend(buffer,
offset,
size,
SocketFlags.None,
onSend,
new AsyncState(buffer, offset, size, socket));
}
#endregion
internal class AsyncState
{
public readonly byte[] buffer;
public readonly int offset;
public readonly int size;
public readonly Socket socket;
public AsyncState(Socket socket)
{
this.socket = socket;
}
public AsyncState(byte[] buffer, int offset, int size, Socket socket)
{
this.buffer = buffer;
this.offset = offset;
this.size = size;
this.socket = socket;
}
}
public void SendMessage(Packet msg)
{
}
#region Event
//private static readonly object EventRun = new object();
public event EventHandler Start;
//{
// add { Events.AddHandler(EventMovePrevious, value); }
// remove { Events.RemoveHandler(EventMovePrevious, value); }
//}
protected virtual void OnRun(EventArgs e)
{
//EventHandler handler = (EventHandler)base.Events[EventMoveNext];
//if (handler != null)
//{
// handler(this, e);
//}
}
#endregion
public void Dispose()
{
}
/// <summary>
/// 处理封包
/// </summary>
/// <param name="msg"></param>
void DispatchMsg(Packet msg)
{
//switch (msg.cmd)
//{
// case cmd.GetUserList:
// break;
// case cmd.Login:
// Peer peer;
// using (MemoryStream ms = new MemoryStream(msg.Content))
// {
// System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binSerialer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
// peer = (Peer)binSerialer.Deserialize(ms);
// }
// //Win32API.SendMessage(m_hWnd,
// break;
// default:
// break;
//}
}
}
}