C# SocketAsyncEventArgs Server

SocketAsyncEventArgs 连接池

SocketAsyncEventArgsPool
using System;
using System.Net.Sockets;
using System.Collections.Generic;

namespace LinFx.Net.Sockets
{
class SocketAsyncEventArgsPool
{
private readonly Stack<SocketAsyncEventArgs> m_pool;
private readonly object syncLocker = new object();

public SocketAsyncEventArgsPool(int capacity)
{
m_pool
= new Stack<SocketAsyncEventArgs>(capacity);
}

public void Push(SocketAsyncEventArgs item)
{
if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); }
lock (syncLocker)
{
if (item.AcceptSocket != null)
item.AcceptSocket
= null;
m_pool.Push(item);
}
}

public SocketAsyncEventArgs Pop()
{
lock (syncLocker)
return m_pool.Pop();
}

public int Count { get { return m_pool.Count; } }
}
}

 AsyncUserToken

AsyncUserToken
using System; using System.Net.Sockets; using System.Collections.Generic;
namespace LinFx.Net.Sockets { public class AsyncUserToken { Socket m_socket;
public AsyncUserToken() : this(null) { }
public AsyncUserToken(Socket socket) { m_socket = socket; }
public Socket Socket { get { return m_socket; } set { m_socket = value; } }
public ISession Session { get; set; } //public Context Context { get; set; } } }

缓冲区 

BufferManager
using System;
using System.Net.Sockets;
using System.Collections.Generic;

namespace LinFx.Net.Sockets
{
internal sealed class BufferManager
{
int m_numBytes; // the total number of bytes controlled by the buffer pool
byte[] m_buffer; // the underlying byte array maintained by the Buffer Manager
Stack<int> m_freeIndexPool; //
int m_currentIndex;
int m_bufferSize;

public BufferManager(int totalBytes, int bufferSize)
{
m_numBytes
= totalBytes;
m_currentIndex
= 0;
m_bufferSize
= bufferSize;
m_freeIndexPool
= new Stack<int>();
}

/// <summary>
/// Allocates buffer space used by the buffer pool
/// </summary>
public void InitBuffer()
{
// create one big large buffer and divide that out to each SocketAsyncEventArg object
m_buffer = new byte[m_numBytes];
}

/// <summary>
/// Assigns a buffer from the buffer pool to the specified SocketAsyncEventArgs object
/// </summary>
/// <returns>true if the buffer was successfully set, else false</returns>
public bool SetBuffer(SocketAsyncEventArgs args)
{
if (m_freeIndexPool.Count > 0)
{
args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
}
else
{
if ((m_numBytes - m_bufferSize) < m_currentIndex)
return false;
args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
m_currentIndex
+= m_bufferSize;
}
return true;
}

/// <summary>
/// Removes the buffer from a SocketAsyncEventArg object. This frees the buffer back to the
/// buffer pool
/// </summary>
public void FreeBuffer(SocketAsyncEventArgs args)
{
m_freeIndexPool.Push(args.Offset);
args.SetBuffer(
null, 0, 0);
}
}
}

Session

Session
using System;
using System.Net;
using System.Net.Sockets;

namespace LinFx.Net.Sockets
{
public interface ISession
{
void Initize(Socket socket);
void ProcessRecv(SocketAsyncEventArgs e);
void ProcessSend(SocketAsyncEventArgs e);
IPEndPoint LocalEndPoint {
get; }
IPEndPoint RemoteEndPoint {
get; }
event EventHandler<SocketAsyncEventArgs> Closed;
}

public abstract class Session : ISession
{
public Context Context { get; private set; }
public Socket Client { get; private set; }
public IPEndPoint LocalEndPoint { get { return (IPEndPoint)Client.LocalEndPoint; } }
public IPEndPoint RemoteEndPoint { get { return (IPEndPoint)Client.RemoteEndPoint; } }
public event EventHandler<SocketAsyncEventArgs> Closed;

//public virtual void RecvResponse(SocketContext context, byte[] data) { }
//public virtual void RecvResponse(SocketContext context, byte[] data) { }

//public virtual void SendResponse(SocketContext context, byte[] data) { }
//public virtual void SendResponse(SocketContext context, byte[] data) { }

public void Initize(Socket socket)
{
this.Client = socket;
}

public virtual void ProcessRecv(SocketAsyncEventArgs e)
{
if (e.BytesTransferred <= 0 || e.SocketError != SocketError.Success)
{
OnClosed(e);
return;
}

AsyncUserToken token
= (AsyncUserToken)e.UserToken;
e.SetBuffer(e.Offset, e.BytesTransferred);

string str = "Hello World";
byte[] buffer = System.Text.Encoding.Default.GetBytes(str);
e.SetBuffer(buffer,
0, buffer.Length);


bool willRaiseEvent = token.Socket.SendAsync(e);
if (!willRaiseEvent)
{
ProcessSend(e);
}
}

public virtual void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
OnClosed(e);
return;
}

AsyncUserToken token
= (AsyncUserToken)e.UserToken;
bool willRaiseEvent = token.Socket.ReceiveAsync(e);
if (!willRaiseEvent)
{
ProcessRecv(e);
}
}

public virtual void OnClosed(SocketAsyncEventArgs e)
{
if (Closed != null)
Closed(
this, e);
}
}
}

  这里 Session 只是简单发回 "Hello World"

Server

SocketAsyncEventArgs Server
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;

namespace LinFx.Net.Sockets
{
public class Server
{
int m_nConnection;
BufferManager m_BufferManager;
//缓冲区
SocketAsyncEventArgsPool m_ReadWritePool; //连接池
Socket m_sListen; //服务端
Type TSession;
Semaphore m_MaxConnectionSemaphore;

public Server(int n, Type t)
{
this.m_nConnection = n;
this.TSession = t;
}

public void Run()
{
new Thread(new ThreadStart(ListenThreadMethod)).Start();
}

private void ListenThreadMethod()
{
//int bufferSize = Math.Max(AppServer.Config.ReceiveBufferSize, AppServer.Config.SendBufferSize);
//if (bufferSize <= 0)
// bufferSize = 1024 * 8;
int receiveBufferSize = 1024 * 8;
m_BufferManager
= new BufferManager(receiveBufferSize * m_nConnection * 2, receiveBufferSize);
m_ReadWritePool
= new SocketAsyncEventArgsPool(5);
m_MaxConnectionSemaphore
= new Semaphore(5, 5);

m_BufferManager.InitBuffer();

SocketAsyncEventArgs socketEventArg;

for (int i = 0; i < 5; i++)
{
socketEventArg
= new SocketAsyncEventArgs();
socketEventArg.Completed
+= new EventHandler<SocketAsyncEventArgs>(IO_Completed);
socketEventArg.UserToken
= new AsyncUserToken();

m_BufferManager.SetBuffer(socketEventArg);
m_ReadWritePool.Push(socketEventArg);
}

IPAddress ip
= IPAddress.Parse("222.222.222.187");
IPEndPoint ipe
= new IPEndPoint(ip, 60000);

m_sListen
= new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_sListen.Bind(ipe);
m_sListen.Listen(
50);

PostAccept(
null);
}

public void PostAccept(SocketAsyncEventArgs socketEventArgs)
{
if (socketEventArgs == null)
{
socketEventArgs
= new SocketAsyncEventArgs();
socketEventArgs.Completed
+= new EventHandler<SocketAsyncEventArgs>(socketEventArgs_Completed);
}
else
{
socketEventArgs.AcceptSocket
= null;
}

m_MaxConnectionSemaphore.WaitOne();
bool willRaiseEvent = m_sListen.AcceptAsync(socketEventArgs);
if (!willRaiseEvent)
{
ProcessAccept(socketEventArgs);
}
}

private void ProcessAccept(SocketAsyncEventArgs e)
{
SocketAsyncEventArgs socketEventArgs
= m_ReadWritePool.Pop();

ISession session
= Activator.CreateInstance(TSession) as ISession;
session.Closed
+= new EventHandler<SocketAsyncEventArgs>(Session_Closed);
session.Initize(e.AcceptSocket);

((AsyncUserToken)(socketEventArgs.UserToken)).Socket
= e.AcceptSocket;
((AsyncUserToken)(socketEventArgs.UserToken)).Session
= session;

bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(socketEventArgs);
if (!willRaiseEvent)
{
session.ProcessRecv(socketEventArgs);
}
PostAccept(e);
}

void socketEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}

void IO_Completed(object sender, SocketAsyncEventArgs e)
{
AsyncUserToken token
= e.UserToken as AsyncUserToken;
ISession session
= token.Session;

if (session == null)
return;

switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
session.ProcessRecv(e);
break;
case SocketAsyncOperation.Send:
session.ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}

void Session_Closed(object sender, SocketAsyncEventArgs e)
{
AsyncUserToken token
= e.UserToken as AsyncUserToken;
try
{
token.Socket.Shutdown(SocketShutdown.Send);
}
catch (Exception) { }
token.Socket.Close();
m_MaxConnectionSemaphore.Release();
m_ReadWritePool.Push(e);
}


}
}

  

posted @ 2011-07-16 11:11  一浩瀚星空一  阅读(4747)  评论(1编辑  收藏  举报