SocketServer.cs 6.6 KB
Newer Older
JasonWcx's avatar
JasonWcx 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;

namespace Mozi.HttpEmbedded
{
    /// <summary>
    /// 异步单线程
    /// </summary>
    public class SocketServer
    {
        //private static SocketServer _mSocketServer;
        private int _iPort = 9000;
15
        private Dictionary<string,Socket> _socketDocker;
16
        private Socket _sc;
JasonWcx's avatar
JasonWcx 已提交
17 18 19 20 21 22 23 24
        /// <summary>
        /// 服务器启动事件
        /// </summary>
        public event ServerStart OnServerStart;
        /// <summary>
        /// 客户端连接事件
        /// </summary>
        public event ClientConnect OnClientConnect;
25 26 27
        /// <summary>
        /// 客户端断开连接时间
        /// </summary>
JasonWcx's avatar
JasonWcx 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
        public event ClientDisConnect AfterClientDisConnect;
        /// <summary>
        /// 数据接收开始事件
        /// </summary>
        public event ReceiveStart OnReceiveStart;
        /// <summary>
        /// 数据接收完成事件
        /// </summary>
        public event ReceiveEnd AfterReceiveEnd;
        /// <summary>
        /// 服务器停用事件
        /// </summary>
        public event AfterServerStop AfterServerStop;

        /// <summary>
        /// 端口
        /// </summary>
JasonWcx's avatar
JasonWcx 已提交
45
        public int Port
JasonWcx's avatar
JasonWcx 已提交
46 47 48 49 50 51
        {
            get { return _iPort; }
        }

        public Socket SocketMain
        {
52
            get { return _sc; }
JasonWcx's avatar
JasonWcx 已提交
53 54 55 56
        }

        public SocketServer() 
        {
57
            _socketDocker = new Dictionary<string, Socket>();
JasonWcx's avatar
JasonWcx 已提交
58 59 60 61 62 63 64 65 66 67
        }

        //TODO 测试此处是否有BUG
        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <param name="port"></param>
        public void StartServer(int port)
        {
            _iPort = port;
68
            if (_sc == null)
JasonWcx's avatar
JasonWcx 已提交
69
            {
70
                _sc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
JasonWcx's avatar
JasonWcx 已提交
71 72 73
            }
            else
            {
74
                _sc.Close();
JasonWcx's avatar
JasonWcx 已提交
75 76
            }
            System.Net.IPEndPoint endpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Any, _iPort);
77 78
            _sc.Bind(endpoint);
            _sc.Listen(_iPort);            
JasonWcx's avatar
JasonWcx 已提交
79 80 81 82 83
            //回调服务器启动事件
            if (OnServerStart != null) 
            {
                OnServerStart(this, new ServerArgs() { StartTime=DateTime.Now,StopTime=DateTime.MinValue });
            }
84
            _sc.BeginAccept(new AsyncCallback(CallbackAccept), _sc);
JasonWcx's avatar
JasonWcx 已提交
85 86 87 88 89 90 91 92 93
        }
        /// <summary>
        /// 关闭服务器
        /// </summary>
        public void StopServer() 
        {
            _socketDocker.Clear();
            try
            {
94
                _sc.Shutdown(SocketShutdown.Both);
JasonWcx's avatar
JasonWcx 已提交
95 96
                if (AfterServerStop != null) 
                {
97
                    AfterServerStop(_sc, null);
JasonWcx's avatar
JasonWcx 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
                }
            }
            catch 
            { 
            
            }
        }
        /// <summary>
        /// 开始连接回调
        /// </summary>
        /// <param name="iar"></param>
        private void CallbackAccept(IAsyncResult iar)
        {
            Socket server = (Socket)iar.AsyncState;
            Socket client = server.EndAccept(iar);
113
            
JasonWcx's avatar
JasonWcx 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127
            server.BeginAccept(CallbackAccept, server);
            if (OnClientConnect != null) 
            {
                OnClientConnect(this, new ClientConnectArgs() { 
                    Client=client
                });
            }
            StateObject so = new StateObject() 
            { 
                WorkSocket = client,
                Id = Guid.NewGuid().ToString(),
                IP = ((System.Net.IPEndPoint)client.RemoteEndPoint).Address.ToString(),
                RemotePort = ((System.Net.IPEndPoint)client.RemoteEndPoint).Port,
            };
128
            _socketDocker.Add(so.Id, client);
JasonWcx's avatar
JasonWcx 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
            try
            {
                client.BeginReceive(so.Buffer, 0, StateObject.BufferSize, 0, CallbackReceive, so);
                if (OnReceiveStart != null)
                {
                    OnReceiveStart(this, new DataTransferArgs());
                }
            }
            catch(Exception ex)
            {
                var ex2 = ex;
            }
        }
        /// <summary>
        /// 接收数据回调
        /// </summary>
        /// <param name="iar"></param>
        private void CallbackReceive(IAsyncResult iar)
        {
            StateObject so = (StateObject)iar.AsyncState;
            Socket client = so.WorkSocket;
150 151 152
            if (client.Connected)
            {
                int iByteRead = client.EndReceive(iar);
JasonWcx's avatar
JasonWcx 已提交
153
                   
154 155 156 157
                if (iByteRead >0)
                {
                    //置空数据连接
                    so.ResetBuffer(iByteRead);
158
                    if (client.Available > 0){
159 160
                        //Thread.Sleep(10);
                        client.BeginReceive(so.Buffer, 0, StateObject.BufferSize, 0, CallbackReceive, so);
161
                    }else{
162
                        _socketDocker.Remove(so.Id);
JasonWcx's avatar
JasonWcx 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176
                        if (AfterReceiveEnd != null)
                        {
                            AfterReceiveEnd(this,
                                new DataTransferArgs()
                                {
                                    Data = so.Data.ToArray(),
                                    IP = so.IP,
                                    Port = so.RemotePort,
                                    Socket = so.WorkSocket
                                });
                        }
                    }
                }
                else 
177 178
                {
                    _socketDocker.Remove(so.Id);
JasonWcx's avatar
JasonWcx 已提交
179 180 181 182 183 184 185 186 187 188 189 190
                    if (AfterReceiveEnd != null)
                    {
                        AfterReceiveEnd(this,
                            new DataTransferArgs()
                            {
                                Data = so.Data.ToArray(),
                                IP = so.IP,
                                Port = so.RemotePort,
                                Socket = so.WorkSocket
                            });
                    }
                }
191 192 193
            }
            else 
            {
194
                _socketDocker.Remove(so.Id);
195 196 197 198 199 200 201 202 203 204 205 206 207
                if (AfterReceiveEnd != null)
                {
                    AfterReceiveEnd(this,
                        new DataTransferArgs()
                        {
                            Data = so.Data.ToArray(),
                            IP = so.IP,
                            Port = so.RemotePort,
                            Socket = so.WorkSocket
                        });
                }
                client.Dispose();
            }
JasonWcx's avatar
JasonWcx 已提交
208 209 210
        }
    }
}