using System;
using System.Collections.Concurrent;
using System.Net.Sockets;
namespace Mozi.HttpEmbedded
{
//TODO 加入定时器并利用POLL判断远端是否断开
//TODO 实现链接复用
//TODO 解决接收文件内存占用过大,无法及时释放的问题
///
/// 异步单线程
///
public class SocketServer
{
protected int _iport = 80;
protected int _maxListenCount = 65535;
protected readonly ConcurrentDictionary _socketDocker;
protected Socket _sc;
///
/// 服务器启动事件
///
public event ServerStart OnServerStart;
///
/// 客户端连接事件
///
public event ClientConnect OnClientConnect;
///
/// 客户端断开连接时间
///
public event ClientDisConnect AfterClientDisConnect;
///
/// 数据接收开始事件
///
public event ReceiveStart OnReceiveStart;
///
/// 数据接收完成事件
///
public event ReceiveEnd AfterReceiveEnd;
///
/// 服务器停用事件
///
public event AfterServerStop AfterServerStop;
///
/// 端口
///
public int Port
{
get { return _iport; }
}
public Socket SocketMain
{
get { return _sc; }
}
public SocketServer()
{
_socketDocker = new ConcurrentDictionary();
}
//TODO 测试此处是否有BUG
///
/// 启动服务器
///
///
public void StartServer(int port)
{
_iport = port;
if (_sc == null)
{
_sc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
}
else
{
_sc.Close();
}
System.Net.IPEndPoint endpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any, _iport);
//允许端口复用
_sc.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_sc.Bind(endpoint);
_sc.Listen(_maxListenCount);
//回调服务器启动事件
if (OnServerStart != null)
{
OnServerStart(this, new ServerArgs() { StartTime = DateTime.Now, StopTime = DateTime.MinValue });
}
_sc.BeginAccept(new AsyncCallback(CallbackAccept), _sc);
}
///
/// 关闭服务器
///
public void StopServer()
{
_socketDocker.Clear();
try
{
_sc.Shutdown(SocketShutdown.Both);
if (AfterServerStop != null)
{
AfterServerStop(_sc, null);
}
}
catch
{
}
}
///
/// 开始连接回调
///
///
protected void CallbackAccept(IAsyncResult iar)
{
Socket server = (Socket)iar.AsyncState;
//接受新连接传入
server.BeginAccept(CallbackAccept, server);
Socket client = server.EndAccept(iar);
if (OnClientConnect != null)
{
//TODO .NetCore不再支持异步委托,需要重新实现
OnClientConnect(this, new ClientConnectArgs()
{
Client = client
});
}
StateObject so = new StateObject()
{
WorkSocket = client,
Id = Guid.NewGuid().ToString(),
IP = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString(),
ConnectTime = DateTime.Now,
RemotePort = ((System.Net.IPEndPoint)client.RemoteEndPoint).Port,
};
_socketDocker.TryAdd(so.Id, client);
try
{
client.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, CallbackReceived, so);
if (OnReceiveStart != null)
{
OnReceiveStart.BeginInvoke(this, new DataTransferArgs(), null, null);
}
}
catch (Exception ex)
{
var ex2 = ex;
}
}
///
/// 接收数据回调
///
///
internal void CallbackReceived(IAsyncResult iar)
{
StateObject so = (StateObject)iar.AsyncState;
Socket client = so.WorkSocket;
if (client.Connected)
{
try
{
int iByteRead = client.EndReceive(iar);
if (iByteRead > 0)
{
//置空数据缓冲区
so.ResetBuffer(iByteRead);
if (client.Available > 0)
{
//Thread.Sleep(10);
client.BeginReceive(so.Buffer, 0, so.Buffer.Length, SocketFlags.None, CallbackReceived, so);
}
else
{
InvokeAfterReceiveEnd(so, client);
}
}
else
{
InvokeAfterReceiveEnd(so, client);
}
}
finally
{
}
}
else
{
InvokeAfterReceiveEnd(so, client);
}
}
private void InvokeAfterReceiveEnd(StateObject so, Socket client)
{
try
{
RemoveClientSocket(so);
if (AfterReceiveEnd != null)
{
AfterReceiveEnd(this,
new DataTransferArgs()
{
Data = so.Data.ToArray(),
IP = so.IP,
Port = so.RemotePort,
Socket = so.WorkSocket,
Client = client,
State = so
});
}
}finally{
}
}
//TODO 此处开启Socket状态监听,对断开的链接进行关闭销毁
private void RemoveClientSocket(StateObject so)
{
Socket client;
_socketDocker.TryRemove(so.Id, out client);
}
}
}