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); } } }