110,556
社区成员
发帖
与我相关
我的任务
分享
using IOCP.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace IOCP.Base
{
public class AppServer
{
public event SessionConnectedHandler OnSessionConnected;
public event SessionLostConnectHandler OnSessonLostConnect;
public event SessionMessageArrived OnSessionMessageArrived;
private ReceiveFilter filter;
private RequestSerializer serializer;
private ServerConfig config;
private BufferManager bufferManager;
private SAEAPool seaPool;
private MemoryPool memoryPool;
private Socket _listener;
private System.Timers.Timer tmrTimeout;
private Dictionary<string, SocketAsyncEventArgs> clients;
public AppServer(ReceiveFilter filter, RequestSerializer serializer)
{
this.filter = filter;
this.serializer = serializer;
}
public void Start(ServerConfig config)
{
if (_listener != null)
{
return;
}
this.config = config;
filter.Charset = config.Charset;
Init();
StartListen();
}
public void Stop()
{
try
{
_listener.Close();
tmrTimeout.Stop();
lock (this)
{
foreach (var kp in clients)
{
CloseSocket(kp.Value, CloseReason.ServerShutdown);
}
}
}
catch (Exception ex)
{
}
}
private void Init()
{
clients = new Dictionary<string, SocketAsyncEventArgs>();
bufferManager = new BufferManager(config.MaxConnectionNumber * config.ReceiveBufferSize, config.ReceiveBufferSize);
memoryPool = new MemoryPool(config.MaxConnectionNumber, config.ClientBufferSize);
seaPool = new SAEAPool(config.MaxConnectionNumber);
SocketAsyncEventArgs readWriteEventArg;
for (int i = 0; i < config.MaxConnectionNumber; i++)
{
readWriteEventArg = new SocketAsyncEventArgs();
readWriteEventArg.Completed += IOCompleted;
bufferManager.SetBuffer(readWriteEventArg);
seaPool.Push(readWriteEventArg);
}
}
private void StartListen()
{
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(new IPEndPoint(IPAddress.Any, config.Port));
_listener.Listen(config.ListenBlockNumber);
StartAccept(null);
tmrTimeout = new System.Timers.Timer();
tmrTimeout.Elapsed += tmrTimeout_Elapsed;
tmrTimeout.Interval = config.TimeoutCheckInterval * 1000;
tmrTimeout.Start();
}
private void tmrTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
List<SocketAsyncEventArgs> ls = new List<SocketAsyncEventArgs>();
lock (this)
{
foreach (var kp in clients)
{
AppSession session = kp.Value.UserToken as AppSession;
if ((DateTime.Now - session.SocketSession.LastResponseTime).TotalSeconds > config.ClientTimeout)
{
ls.Add(kp.Value);
}
}
foreach (var c in ls)
{
string addressId = ((AppSession)c.UserToken).SocketSession.S.RemoteEndPoint.ToString();
try
{
CloseSocket(c, CloseReason.Timeout);
}
catch (Exception ex)
{
}
finally
{
clients.Remove(addressId);
}
}
}
}
private void StartAccept(SocketAsyncEventArgs e)
{
try
{
if (e == null)
{
e = new SocketAsyncEventArgs();
e.Completed += AcceptCompleted;
}
else
{
e.AcceptSocket = null;
}
if (!_listener.AcceptAsync(e))
{
ProcessAccept(e);
}
}
catch (Exception ex)
{
}
}
private void AcceptCompleted(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void IOCompleted(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
}
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
Socket s = e.AcceptSocket;
if (s != null && s.Connected)
{
SocketAsyncEventArgs reader = seaPool.Pop();
if (reader == null)
{
s.Close();
}
else
{
try
{
ClientBuffer cb = new ClientBuffer(memoryPool.Pop());
SocketSession ss = new SocketSession(s, cb);
AppSession token = new AppSession(ss, config.Charset);
token.Serializer = serializer;
reader.UserToken = token;
lock (this)
{
clients.Add(s.RemoteEndPoint.ToString(), e);
}
if (OnSessionConnected != null)
{
OnSessionConnected(token);
}
if (!s.ReceiveAsync(reader))
{
ProcessReceive(e);
}
}
catch (SocketException ex)
{
seaPool.Push(reader);
}
}
}
StartAccept(e);
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
if (e.BytesTransferred > 0)
{
AppSession token = e.UserToken as AppSession;
token.SocketSession.Buffer.Write(e.Buffer, e.Offset, e.BytesTransferred);
//尝试解析缓冲区内容
int offset = 0;
int rest = 0;
RequestInfo req = null;
while ((req = filter.ResolveRequestInfo(token.SocketSession.Buffer.Body, offset, token.SocketSession.Buffer.Length, out rest)) != null)
{
//处理请求
if (OnSessionMessageArrived != null)
{
OnSessionMessageArrived(token, req);
}
offset += rest;
}
token.SocketSession.Buffer.Read(offset);
if (!token.SocketSession.S.ReceiveAsync(e))
{
ProcessReceive(e);
}
}
else
{
CloseSocket(e, CloseReason.ClientClose);
}
}
else
{
CloseSocket(e, CloseReason.SocketError);
}
}
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
//todo
}
else
{
CloseSocket(e, CloseReason.SocketError);
}
}
private void CloseSocket(SocketAsyncEventArgs e, CloseReason closeReason)
{
AppSession token = e.UserToken as AppSession;
try
{
token.SocketSession.S.Shutdown(SocketShutdown.Both);
RaiseDisconnectEvent(e, closeReason);
}
catch (Exception ex)
{
}
finally
{
token.SocketSession.S.Close();
}
memoryPool.Push(token.SocketSession.Buffer.Body);
seaPool.Push(e);
e.UserToken = null;
}
AppServer host = new AppServer(new ReceiveFilter(5), new RequestSerializer(5));
host.Start(new ServerConfig()
{
Port = 13001,
MaxConnectionNumber = 3000,
ListenBlockNumber = 100,
ReceiveBufferSize = 1024,
ClientBufferSize = 4096,
ClientTimeout = 30,
TimeoutCheckInterval = 10
});
host.OnSessionConnected += host_OnSessionConnected;
host.OnSessionMessageArrived += host_OnSessionMessageArrived;
host.OnSessonLostConnect += host_OnSessonLostConnect;
Console.WriteLine("服务器已启动");