├── FastNetwork.sln ├── FastNetwork ├── BaseHost.cs ├── BaseSocketServer.cs ├── Client │ ├── BaseSocketClient.cs │ ├── DefaultSocketClient.cs │ ├── IClientHandler.cs │ ├── Request.cs │ └── RequestException.cs ├── ConnectionCollection.cs ├── DefaultConfigure.cs ├── DefaultConnection.cs ├── Event │ ├── DisconnectedHandler.cs │ ├── ErrorHandler.cs │ ├── MessageReceivedHandler.cs │ ├── SendCallbackHandler.cs │ └── StartSendingHandler.cs ├── FastNetwork.csproj ├── IConnection.cs ├── IHost.cs ├── ISAEAPool.cs ├── IServerHandler.cs ├── ISocketListener.cs ├── IUdpServer.cs ├── IUdpServerHandler.cs ├── Log │ ├── ConsoleListener.cs │ ├── DiagnosticListener.cs │ ├── ITraceListener.cs │ ├── ListenerWrapper.cs │ └── Trace.cs ├── Packet.cs ├── Properties │ └── AssemblyInfo.cs ├── Protocol │ ├── BadProtocolException.cs │ ├── DefaultBinaryProtocol.cs │ ├── IDecoder.cs │ ├── IEncoder.cs │ ├── IProtocol.cs │ ├── IUdpProtocol.cs │ └── PacketBuilder.cs ├── ReceivePacket.cs ├── SocketConnector.cs ├── SocketListener.cs ├── SocketServer.cs ├── UdpServer.cs ├── UdpSession.cs ├── Utils │ ├── ConsistentHashContainer.cs │ ├── Date.cs │ ├── DisposableBase.cs │ ├── IPUtility.cs │ ├── NetworkBitConverter.cs │ ├── ReflectionHelper.cs │ └── TaskEx.cs ├── bin │ └── Debug │ │ ├── FastNetwork.dll │ │ └── FastNetwork.pdb └── obj │ └── Debug │ ├── DesignTimeResolveAssemblyReferencesInput.cache │ ├── FastNetwork.csproj.FileListAbsolute.txt │ ├── FastNetwork.dll │ └── FastNetwork.pdb ├── PluginEngine ├── DefaultPlugin.cs ├── IPlugin.cs ├── InnerPlugin.cs ├── PluginAttribute.cs ├── PluginDescription.cs ├── PluginEngine.csproj ├── PluginInfo.cs ├── PluginList.cs ├── PluginManager.cs ├── PluginState.cs ├── Properties │ └── AssemblyInfo.cs ├── bin │ └── Debug │ │ ├── FastNetwork.dll │ │ ├── FastNetwork.pdb │ │ ├── PluginEngine.dll │ │ └── PluginEngine.pdb └── obj │ └── Debug │ ├── DesignTimeResolveAssemblyReferencesInput.cache │ ├── PluginEngine.csproj.FileListAbsolute.txt │ ├── PluginEngine.csprojResolveAssemblyReference.cache │ ├── PluginEngine.dll │ └── PluginEngine.pdb ├── README.md ├── Test ├── DefaultDecoder.cs ├── DefaultEncoder.cs ├── IMessage.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── ServerHandler.cs ├── Test.csproj ├── UserInfo.cs ├── bin │ └── Debug │ │ ├── Debug.rar │ │ ├── FastNetwork.dll │ │ ├── FastNetwork.pdb │ │ ├── Test.exe │ │ ├── Test.pdb │ │ ├── Test.vshost.exe │ │ └── Test.vshost.exe.manifest └── obj │ └── Debug │ ├── DesignTimeResolveAssemblyReferencesInput.cache │ ├── Test.csproj.FileListAbsolute.txt │ ├── Test.csprojResolveAssemblyReference.cache │ ├── Test.exe │ └── Test.pdb └── TestClient ├── ClientHandler.cs ├── DefaultDecoder.cs ├── DefaultEncoder.cs ├── IMessage.cs ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── TestClient.csproj ├── UserInfo.cs ├── bin └── Debug │ ├── FastNetwork.dll │ ├── FastNetwork.pdb │ ├── TestClient.exe │ ├── TestClient.pdb │ ├── TestClient.vshost.exe │ └── TestClient.vshost.exe.manifest └── obj └── Debug ├── DesignTimeResolveAssemblyReferencesInput.cache ├── TestClient.csproj.FileListAbsolute.txt ├── TestClient.csprojResolveAssemblyReference.cache ├── TestClient.exe └── TestClient.pdb /FastNetwork.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastNetwork", "FastNetwork\FastNetwork.csproj", "{EAEF8B76-66B2-4502-88DE-19D80F016A6B}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginEngine", "PluginEngine\PluginEngine.csproj", "{DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {EAEF8B76-66B2-4502-88DE-19D80F016A6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {EAEF8B76-66B2-4502-88DE-19D80F016A6B}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {EAEF8B76-66B2-4502-88DE-19D80F016A6B}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EAEF8B76-66B2-4502-88DE-19D80F016A6B}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700}.Release|Any CPU.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /FastNetwork/BaseHost.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Collections.Concurrent; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | 8 | namespace FastNetwork 9 | { 10 | /// 11 | /// base host 12 | /// 13 | public abstract class BaseHost : IHost 14 | { 15 | #region Members 16 | private long _connectionID = 1000L; 17 | /// 18 | /// connection collection 19 | /// 20 | protected readonly ConnectionCollection _listConnections = new ConnectionCollection(); 21 | private readonly ConcurrentStack _stack = new ConcurrentStack(); 22 | #endregion 23 | 24 | #region Constructors 25 | /// 26 | /// new 27 | /// 28 | /// 29 | /// 30 | /// socketBufferSize 31 | /// messageBufferSize 32 | protected BaseHost(int socketBufferSize, int messageBufferSize) 33 | { 34 | if (socketBufferSize < 1) throw new ArgumentOutOfRangeException("socketBufferSize"); 35 | if (messageBufferSize < 1) throw new ArgumentOutOfRangeException("messageBufferSize"); 36 | 37 | this.SocketBufferSize = socketBufferSize; 38 | this.MessageBufferSize = messageBufferSize; 39 | } 40 | #endregion 41 | 42 | #region IHost Members 43 | /// 44 | /// get socket buffer size 45 | /// 46 | public int SocketBufferSize 47 | { 48 | get; 49 | private set; 50 | } 51 | /// 52 | /// get message buffer size 53 | /// 54 | public int MessageBufferSize 55 | { 56 | get; 57 | private set; 58 | } 59 | /// 60 | /// 生成下一个连接ID 61 | /// 62 | /// 63 | public long NextConnectionID() 64 | { 65 | return Interlocked.Increment(ref this._connectionID); 66 | } 67 | /// 68 | /// get by connectionID 69 | /// 70 | /// 71 | /// 72 | public IConnection GetConnectionByID(long connectionID) 73 | { 74 | return this._listConnections.Get(connectionID); 75 | } 76 | 77 | /// 78 | /// 启动 79 | /// 80 | public virtual void Start() 81 | { 82 | } 83 | /// 84 | /// 停止 85 | /// 86 | public virtual void Stop() 87 | { 88 | this._listConnections.DisconnectAll(); 89 | } 90 | #endregion 91 | 92 | #region Protected Methods 93 | /// 94 | /// register connection 95 | /// 96 | /// 97 | /// connection is null 98 | protected void RegisterConnection(IConnection connection) 99 | { 100 | if (connection == null) throw new ArgumentNullException("connection"); 101 | if (!connection.Active) return; 102 | 103 | connection.StartSending += new StartSendingHandler(this.OnStartSending); 104 | connection.SendCallback += new SendCallbackHandler(this.OnSendCallback); 105 | connection.MessageReceived += new MessageReceivedHandler(this.OnMessageReceived); 106 | connection.Disconnected += new DisconnectedHandler(this.OnDisconnected); 107 | connection.Error += new ErrorHandler(this.OnError); 108 | 109 | this._listConnections.Add(connection); 110 | this.OnConnected(connection); 111 | } 112 | /// 113 | /// OnConnected 114 | /// 115 | /// 116 | protected virtual void OnConnected(IConnection connection) 117 | { 118 | Log.Trace.Debug(string.Concat("socket connected, id:", connection.ConnectionID.ToString(), 119 | ", remot endPoint:", connection.RemoteEndPoint == null ? string.Empty : connection.RemoteEndPoint.ToString(), 120 | ", local endPoint:", connection.LocalEndPoint == null ? string.Empty : connection.LocalEndPoint.ToString())); 121 | } 122 | /// 123 | /// OnStartSending 124 | /// 125 | /// 126 | /// 127 | protected virtual void OnStartSending(IConnection connection, Packet packet) 128 | { 129 | } 130 | /// 131 | /// OnSendCallback 132 | /// 133 | /// 134 | /// 135 | protected virtual void OnSendCallback(IConnection connection, SendCallbackEventArgs e) 136 | { 137 | } 138 | /// 139 | /// OnMessageReceived 140 | /// 141 | /// 142 | /// 143 | protected virtual void OnMessageReceived(IConnection connection, MessageReceivedEventArgs e) 144 | { 145 | } 146 | /// 147 | /// OnDisconnected 148 | /// 149 | /// 150 | /// 151 | protected virtual void OnDisconnected(IConnection connection, Exception ex) 152 | { 153 | this._listConnections.Remove(connection.ConnectionID); 154 | 155 | connection.StartSending -= new StartSendingHandler(this.OnStartSending); 156 | connection.SendCallback -= new SendCallbackHandler(this.OnSendCallback); 157 | connection.MessageReceived -= new MessageReceivedHandler(this.OnMessageReceived); 158 | connection.Disconnected -= new DisconnectedHandler(this.OnDisconnected); 159 | connection.Error -= new ErrorHandler(this.OnError); 160 | 161 | Log.Trace.Debug(string.Concat("socket disconnected, id:", connection.ConnectionID.ToString(), 162 | ", remot endPoint:", connection.RemoteEndPoint == null ? string.Empty : connection.RemoteEndPoint.ToString(), 163 | ", local endPoint:", connection.LocalEndPoint == null ? string.Empty : connection.LocalEndPoint.ToString(), 164 | ex == null ? string.Empty : string.Concat(", reason is: ", ex.ToString()))); 165 | } 166 | /// 167 | /// OnError 168 | /// 169 | /// 170 | /// 171 | protected virtual void OnError(IConnection connection, Exception ex) 172 | { 173 | Log.Trace.Error(ex.Message, ex); 174 | } 175 | #endregion 176 | 177 | #region ISAEAPool Members 178 | /// 179 | /// get 180 | /// 181 | /// 182 | public SocketAsyncEventArgs GetSocketAsyncEventArgs() 183 | { 184 | SocketAsyncEventArgs e; 185 | if (this._stack.TryPop(out e)) return e; 186 | 187 | e = new SocketAsyncEventArgs(); 188 | e.SetBuffer(new byte[this.MessageBufferSize], 0, this.MessageBufferSize); 189 | return e; 190 | } 191 | /// 192 | /// release 193 | /// 194 | /// 195 | public void ReleaseSocketAsyncEventArgs(SocketAsyncEventArgs e) 196 | { 197 | if (e.Buffer == null || e.Buffer.Length != this.MessageBufferSize) 198 | { 199 | e.Dispose(); return; 200 | } 201 | 202 | if (this._stack.Count >= 50000) { e.Dispose(); return; } 203 | 204 | this._stack.Push(e); 205 | } 206 | #endregion 207 | } 208 | } -------------------------------------------------------------------------------- /FastNetwork/BaseSocketServer.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace FastNetwork 4 | { 5 | /// 6 | /// abstract socket server 7 | /// 8 | public abstract class BaseSocketServer : BaseHost 9 | { 10 | /// 11 | /// new 12 | /// 13 | /// 14 | /// 15 | protected BaseSocketServer(int socketBufferSize, int messageBufferSize) 16 | : base(socketBufferSize, messageBufferSize) 17 | { 18 | } 19 | 20 | /// 21 | /// add socket listener 22 | /// 23 | /// 24 | /// 25 | /// 26 | public abstract ISocketListener AddListener(string name, IPEndPoint endPoint); 27 | } 28 | } -------------------------------------------------------------------------------- /FastNetwork/Client/BaseSocketClient.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Collections.Concurrent; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Net.Sockets; 9 | using System.Threading; 10 | 11 | namespace FastNetwork.Client 12 | { 13 | /// 14 | /// socket client 15 | /// 16 | public abstract class BaseSocketClient : BaseHost 17 | { 18 | #region Private Members 19 | private readonly IProtocol _protocol = null; 20 | 21 | private readonly int _millisecondsSendTimeout; 22 | private readonly int _millisecondsReceiveTimeout; 23 | 24 | private readonly IClientHandler _handler = null; 25 | 26 | private readonly PendingSendQueue _pendingQueue = null; 27 | 28 | private readonly int _port; 29 | 30 | private readonly IPAddress _remote; 31 | 32 | static AutoResetEvent autoEvent = new AutoResetEvent(false); 33 | 34 | 35 | #endregion 36 | 37 | #region Constructors 38 | /// 39 | /// new 40 | /// 41 | /// 42 | public BaseSocketClient(IPAddress remote, int port, IClientHandler handler) 43 | : this(new DefaultBinaryProtocol(), 8192, 8192, 3000, 3000) 44 | { 45 | if (handler == null) throw new ArgumentNullException("handler"); 46 | this._handler = handler; 47 | this._remote = remote; 48 | this._port = port; 49 | } 50 | /// 51 | /// new 52 | /// 53 | /// 54 | /// 55 | /// 56 | /// 57 | /// 58 | /// protocol is null 59 | public BaseSocketClient(IProtocol protocol, 60 | int socketBufferSize, 61 | int messageBufferSize, 62 | int millisecondsSendTimeout, 63 | int millisecondsReceiveTimeout) 64 | : base(socketBufferSize, messageBufferSize) 65 | { 66 | if (protocol == null) throw new ArgumentNullException("protocol"); 67 | this._protocol = protocol; 68 | 69 | this._millisecondsSendTimeout = millisecondsSendTimeout; 70 | this._millisecondsReceiveTimeout = millisecondsReceiveTimeout; 71 | 72 | this._pendingQueue = new PendingSendQueue(this, millisecondsSendTimeout); 73 | } 74 | #endregion 75 | 76 | #region Public Method 77 | 78 | public override void Start() 79 | { 80 | SocketConnector node = null; 81 | IPEndPoint remote = new IPEndPoint(this._remote, this._port); 82 | //注意 这里SocketConnector的第三个参数不能是OnConnected 否则会死循环 83 | node = new SocketConnector("default", remote, this, base.RegisterConnection, OnDisconnected); 84 | node.Start(); 85 | autoEvent.WaitOne(); 86 | } 87 | 88 | #endregion 89 | 90 | #region Public Properties 91 | /// 92 | /// 发送超时毫秒数 93 | /// 94 | public int MillisecondsSendTimeout 95 | { 96 | get { return this._millisecondsSendTimeout; } 97 | } 98 | /// 99 | /// 接收超时毫秒数 100 | /// 101 | public int MillisecondsReceiveTimeout 102 | { 103 | get { return this._millisecondsReceiveTimeout; } 104 | } 105 | #endregion 106 | 107 | #region Protected Methods 108 | /// 109 | /// OnResponse 110 | /// 111 | /// 112 | /// 113 | protected virtual void OnResponse(IConnection connection, Object response) 114 | { 115 | try { this._handler.OnReceived(connection, response); } 116 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 117 | } 118 | /// 119 | /// on request send success 120 | /// 121 | /// 122 | /// 123 | protected virtual void OnSendSucess(IConnection connection, Request request) 124 | { 125 | 126 | } 127 | /// 128 | /// on request send failed 129 | /// 130 | /// 131 | /// 132 | protected virtual void OnSendFailed(IConnection connection, Request request) 133 | { 134 | //this.Send(request); 135 | //connection.BeginSend(request); 136 | } 137 | /// 138 | /// on request send timeout 139 | /// 140 | /// 141 | protected virtual void OnSendTimeout(Request request) 142 | { 143 | } 144 | 145 | /// 146 | /// send request 147 | /// 148 | /// 149 | public abstract void Send(Object obj); 150 | 151 | /// 152 | /// send packet 153 | /// 154 | /// 155 | public abstract void SendRequest(Request request); 156 | /// 157 | /// enqueue to pending queue 158 | /// 159 | /// 160 | protected void EnqueueToPendingQueue(Request request) 161 | { 162 | this._pendingQueue.Enqueue(request); 163 | } 164 | /// 165 | /// dequeue from pending queue 166 | /// 167 | /// 168 | protected Request DequeueFromPendingQueue() 169 | { 170 | return this._pendingQueue.Dequeue(); 171 | } 172 | /// 173 | /// dequeue all from pending queue. 174 | /// 175 | /// 176 | protected Request[] DequeueAllFromPendingQueue() 177 | { 178 | return this._pendingQueue.DequeueAll(); 179 | } 180 | #endregion 181 | 182 | #region Override Methods 183 | /// 184 | /// OnConnected 185 | /// 186 | /// 187 | protected override void OnConnected(IConnection connection) 188 | { 189 | autoEvent.Set(); 190 | connection.BeginReceive();//异步开始接收数据 191 | //触发事件 192 | try { this._handler.OnConnected(connection); } 193 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 194 | } 195 | /// 196 | /// OnStartSending 197 | /// 198 | /// 199 | /// 200 | protected override void OnStartSending(IConnection connection, Packet packet) 201 | { 202 | base.OnStartSending(connection, packet); 203 | try { this._handler.OnStartSending(connection,packet); } 204 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 205 | } 206 | /// 207 | /// OnSendCallback 208 | /// 209 | /// 210 | /// 211 | protected override void OnSendCallback(IConnection connection, SendCallbackEventArgs e) 212 | { 213 | base.OnSendCallback(connection, e); 214 | 215 | try { this._handler.OnSendCallback(connection,e); } 216 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 217 | 218 | var request = e.Packet as Request; 219 | if (request == null) return; 220 | 221 | if (e.Status == SendCallbackStatus.Success) 222 | { 223 | request.CurrConnection = connection; 224 | request.SentTime = DateTime.UtcNow; 225 | this.OnSendSucess(connection, request); 226 | return; 227 | } 228 | 229 | request.CurrConnection = null; 230 | request.SentTime = DateTime.MaxValue; 231 | 232 | if (DateTime.UtcNow.Subtract(request.BeginTime).TotalMilliseconds < this._millisecondsSendTimeout) 233 | { 234 | this.OnSendFailed(connection, request); 235 | return; 236 | } 237 | 238 | //time out 239 | this.OnSendTimeout(request); 240 | 241 | ThreadPool.QueueUserWorkItem(_ => 242 | { 243 | var rex = new RequestException(RequestException.Errors.PendingSendTimeout); 244 | try { request.SetException(rex); } 245 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 246 | }); 247 | } 248 | /// 249 | /// OnMessageReceived 250 | /// 251 | /// 252 | /// 253 | protected override void OnMessageReceived(IConnection connection, MessageReceivedEventArgs e) 254 | { 255 | base.OnMessageReceived(connection, e); 256 | 257 | int readlength; 258 | Object response = null; 259 | ReceivePacket packet = null; 260 | try 261 | { 262 | packet = this._protocol.TryToTranslateMessage(connection, e.Buffer,DefaultConfigure.MaxMessageSize, out readlength); 263 | } 264 | catch (Exception ex) 265 | { 266 | this.OnError(connection, ex); 267 | connection.BeginDisconnect(ex); 268 | e.SetReadlength(e.Buffer.Count); 269 | return; 270 | } 271 | 272 | if (response != null) 273 | { 274 | this.OnResponse(connection, response); 275 | } 276 | e.SetReadlength(readlength); 277 | } 278 | /// 279 | /// OnDisconnected 280 | /// 281 | /// 282 | /// 283 | protected override void OnDisconnected(IConnection connection, Exception e) 284 | { 285 | base.OnDisconnected(connection, e); 286 | try { this._handler.OnDisconnected(connection, e); } 287 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 288 | } 289 | 290 | protected override void OnError(IConnection connection, Exception e) 291 | { 292 | base.OnError(connection, e); 293 | try { this._handler.OnException(connection, e); } 294 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 295 | } 296 | #endregion 297 | 298 | #region Class.PendingSendQueue 299 | /// 300 | /// pending send queue 301 | /// 302 | private class PendingSendQueue 303 | { 304 | #region Private Members 305 | private readonly BaseSocketClient _client = null; 306 | 307 | private readonly int _timeout; 308 | private readonly Timer _timer = null; 309 | private readonly ConcurrentQueue _queue = new ConcurrentQueue(); 310 | #endregion 311 | 312 | #region Constructors 313 | /// 314 | /// new 315 | /// 316 | ~PendingSendQueue() 317 | { 318 | this._timer.Change(Timeout.Infinite, Timeout.Infinite); 319 | this._timer.Dispose(); 320 | } 321 | /// 322 | /// new 323 | /// 324 | /// 325 | /// 326 | public PendingSendQueue(BaseSocketClient client, int millisecondsSendTimeout) 327 | { 328 | this._client = client; 329 | this._timeout = millisecondsSendTimeout; 330 | this._timer = new Timer(_ => 331 | { 332 | this._timer.Change(Timeout.Infinite, Timeout.Infinite); 333 | this.Loop(); 334 | this._timer.Change(1000, 0); 335 | }, null, 1000, 0); 336 | } 337 | #endregion 338 | 339 | #region Public Methods 340 | /// 341 | /// 入列 342 | /// 343 | /// 344 | /// request is null 345 | public void Enqueue(Request request) 346 | { 347 | if (request == null) throw new ArgumentNullException("request"); 348 | this._queue.Enqueue(request); 349 | } 350 | /// 351 | /// dequeue 352 | /// 353 | /// 354 | public Request Dequeue() 355 | { 356 | Request request; 357 | if (this._queue.TryDequeue(out request)) return request; 358 | return null; 359 | } 360 | /// 361 | /// 出列全部 362 | /// 363 | /// 364 | public Request[] DequeueAll() 365 | { 366 | int count = this._queue.Count; 367 | List list = null; 368 | while (count-- > 0) 369 | { 370 | Request request; 371 | if (this._queue.TryDequeue(out request)) 372 | { 373 | if (list == null) list = new List(); 374 | list.Add(request); 375 | } 376 | else break; 377 | } 378 | 379 | if (list != null) return list.ToArray(); 380 | return new Request[0]; 381 | } 382 | #endregion 383 | 384 | #region Private Methods 385 | /// 386 | /// loop 387 | /// 388 | private void Loop() 389 | { 390 | var dtNow = DateTime.UtcNow; 391 | List listSend = null; 392 | List listTimeout = null; 393 | 394 | int count = this._queue.Count; 395 | while (count-- > 0) 396 | { 397 | Request request; 398 | if (this._queue.TryDequeue(out request)) 399 | { 400 | if (dtNow.Subtract(request.BeginTime).TotalMilliseconds < this._timeout) 401 | { 402 | if (listSend == null) listSend = new List(); 403 | listSend.Add(request); continue; 404 | } 405 | 406 | if (listTimeout == null) listTimeout = new List(); 407 | listTimeout.Add(request); 408 | } 409 | else break; 410 | } 411 | 412 | if (listSend != null) 413 | { 414 | //send 函数实际上是调用的DefaultSocketClient的Send函数 415 | //for (int i = 0, l = listSend.Count; i < l; i++) this._client.Send(listSend[i]); 416 | for (int i = 0, l = listSend.Count; i < l; i++) this._client.SendRequest(listSend[i]); 417 | } 418 | 419 | if (listTimeout != null) 420 | { 421 | for (int i = 0, l = listTimeout.Count; i < l; i++) 422 | { 423 | var r = listTimeout[i]; 424 | this._client.OnSendTimeout(r); 425 | ThreadPool.QueueUserWorkItem(_ => 426 | { 427 | try { r.SetException(new RequestException(RequestException.Errors.PendingSendTimeout)); } 428 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 429 | }); 430 | } 431 | } 432 | } 433 | #endregion 434 | } 435 | #endregion 436 | } 437 | } -------------------------------------------------------------------------------- /FastNetwork/Client/DefaultSocketClient.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Protocol; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | 8 | namespace FastNetwork.Client 9 | { 10 | 11 | public class DefaultSocketClient : BaseSocketClient 12 | { 13 | //与服务器的连接 14 | private IConnection _connection = null; 15 | 16 | //编码器 17 | private IEncoder _encoder = null; 18 | 19 | public DefaultSocketClient(IPAddress address, int port, IClientHandler handler,IEncoder encoder) 20 | : base(address, port, handler) 21 | { 22 | if (encoder == null) throw new ArgumentNullException("encoder"); 23 | this._encoder = encoder; 24 | } 25 | 26 | 27 | /// 28 | /// 发送数据到服务器 29 | /// 30 | /// 31 | public override void Send(Object msg) 32 | { 33 | //编码 34 | byte[] data= this._encoder.encode(this._connection,msg); 35 | //构建消息包 36 | byte[] payload = PacketBuilder.ToAsyncBinaryByte(data); 37 | 38 | Request request = new Request(payload, OnException); 39 | if (_connection == null) 40 | this.EnqueueToPendingQueue(request);//没有连接可用,放入待发送队列 41 | else 42 | { 43 | _connection.BeginSend(request); 44 | } 45 | 46 | } 47 | public override void SendRequest(Request request) 48 | { 49 | if (_connection == null) 50 | this.EnqueueToPendingQueue(request);//没有连接可用,放入待发送队列 51 | else 52 | { 53 | _connection.BeginSend(request); 54 | } 55 | } 56 | private void OnException(Exception ex) 57 | { 58 | base.OnError(_connection,ex); 59 | } 60 | protected override void OnConnected(IConnection connection) 61 | { 62 | this._connection = connection; 63 | base.OnConnected(connection); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /FastNetwork/Client/IClientHandler.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace FastNetwork.Client 8 | { 9 | public interface IClientHandler 10 | { 11 | /// 12 | /// 当建立socket连接时,会调用此方法 13 | /// 14 | /// 15 | void OnConnected(IConnection connection); 16 | /// 17 | /// 开始发送 18 | /// 19 | /// 20 | /// 21 | void OnStartSending(IConnection connection, Packet packet); 22 | /// 23 | /// 发送回调 24 | /// 25 | /// 26 | /// 27 | void OnSendCallback(IConnection connection, SendCallbackEventArgs e); 28 | /// 29 | /// 当接收到客户端新消息时,会调用此方法. 30 | /// 31 | /// 32 | /// 33 | void OnReceived(IConnection connection, Object obj); 34 | /// 35 | /// 当socket连接断开时,会调用此方法 36 | /// 37 | /// 38 | /// 39 | void OnDisconnected(IConnection connection, Exception ex); 40 | /// 41 | /// 当发生异常时,会调用此方法 42 | /// 43 | /// 44 | /// 45 | void OnException(IConnection connection, Exception ex); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /FastNetwork/Client/Request.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Client 4 | { 5 | /// 6 | /// request 7 | /// 8 | public class Request : Packet 9 | { 10 | #region Members 11 | 12 | /// 13 | /// get or set receive time out 14 | /// 15 | public int MillisecondsReceiveTimeout; 16 | 17 | /// 18 | /// connectionID 19 | /// 20 | internal IConnection CurrConnection = null; 21 | /// 22 | /// sent time 23 | /// 24 | internal DateTime SentTime = DateTime.MaxValue; 25 | 26 | /// 27 | /// 异常回调 28 | /// 29 | private readonly Action _onException = null; 30 | #endregion 31 | 32 | #region Constructors 33 | /// 34 | /// new 35 | /// 36 | /// seqID 37 | /// command name 38 | /// 发送内容 39 | /// 异常回调 40 | /// onException is null 41 | /// onResult is null 42 | public Request(byte[] payload, Action onException) 43 | : base(payload) 44 | { 45 | if (onException == null) throw new ArgumentNullException("onException"); 46 | this._onException = onException; 47 | } 48 | #endregion 49 | 50 | #region Public Methods 51 | /// 52 | /// set Exception 53 | /// 54 | /// 55 | /// 56 | public bool SetException(Exception ex) 57 | { 58 | this._onException(ex); 59 | return true; 60 | } 61 | #endregion 62 | } 63 | } -------------------------------------------------------------------------------- /FastNetwork/Client/RequestException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Client 4 | { 5 | /// 6 | /// socket request exception 7 | /// 8 | public sealed class RequestException : ApplicationException 9 | { 10 | /// 11 | /// error 12 | /// 13 | public readonly Errors Error; 14 | /// 15 | /// new 16 | /// 17 | /// 18 | /// 19 | public RequestException(Errors error) 20 | : base(string.Concat("errorType:", error.ToString(),string.Empty)) 21 | { 22 | this.Error = error; 23 | } 24 | 25 | /// 26 | /// error type enum 27 | /// 28 | public enum Errors : byte 29 | { 30 | /// 31 | /// 未知 32 | /// 33 | Unknow = 0, 34 | /// 35 | /// 等待发送超时 36 | /// 37 | PendingSendTimeout = 1, 38 | /// 39 | /// 接收超时 40 | /// 41 | ReceiveTimeout = 2 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /FastNetwork/ConnectionCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Linq; 4 | 5 | namespace FastNetwork 6 | { 7 | /// 8 | /// socket connection collection 9 | /// 10 | public sealed class ConnectionCollection 11 | { 12 | #region Private Members 13 | /// 14 | /// key:ConnectionID 15 | /// 16 | private readonly ConcurrentDictionary _dic = new ConcurrentDictionary(); 17 | #endregion 18 | 19 | #region Public Methods 20 | /// 21 | /// add 22 | /// 23 | /// 24 | /// 25 | /// connection is null 26 | public bool Add(IConnection connection) 27 | { 28 | if (connection == null) throw new ArgumentNullException("connection"); 29 | return this._dic.TryAdd(connection.ConnectionID, connection); 30 | } 31 | /// 32 | /// remove connection by id. 33 | /// 34 | /// 35 | /// 36 | public bool Remove(long connectionID) 37 | { 38 | IConnection connection; 39 | return this._dic.TryRemove(connectionID, out connection); 40 | } 41 | /// 42 | /// get by connection id 43 | /// 44 | /// 45 | /// 46 | public IConnection Get(long connectionID) 47 | { 48 | IConnection connection; 49 | this._dic.TryGetValue(connectionID, out connection); 50 | return connection; 51 | } 52 | /// 53 | /// to array 54 | /// 55 | /// 56 | public IConnection[] ToArray() 57 | { 58 | return this._dic.ToArray().Select(c => c.Value).ToArray(); 59 | } 60 | /// 61 | /// count. 62 | /// 63 | /// 64 | public int Count() 65 | { 66 | return this._dic.Count; 67 | } 68 | /// 69 | /// 断开所有连接 70 | /// 71 | public void DisconnectAll() 72 | { 73 | var connections = this.ToArray(); 74 | foreach (var conn in connections) conn.BeginDisconnect(); 75 | } 76 | #endregion 77 | } 78 | } -------------------------------------------------------------------------------- /FastNetwork/DefaultConfigure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork 7 | { 8 | /// 9 | /// 系统默认值 10 | /// 11 | public class DefaultConfigure 12 | { 13 | 14 | public static readonly int SocketBufferSize = 8192; 15 | 16 | public static readonly int MessageBufferSize = 8192; 17 | 18 | public static readonly int MaxMessageSize = 102400; 19 | 20 | public static readonly int MaxConnections = 20000; 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FastNetwork/DefaultConnection.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.Threading; 9 | 10 | namespace FastNetwork 11 | { 12 | /// 13 | /// default socket connection 14 | /// 15 | public class DefaultConnection : IConnection 16 | { 17 | #region Private Members 18 | private int _active = 1;//1表示有效 19 | private IHost _host = null; 20 | private readonly int _messageBufferSize; 21 | 22 | private Socket _socket = null; 23 | 24 | private SocketAsyncEventArgs _saeSend = null; 25 | private SendQueue _sendQueue = null; 26 | private Packet _currSendingPacket = null; 27 | 28 | private SocketAsyncEventArgs _saeReceive = null; 29 | private MemoryStream _tsStream = null;//temporary storage stream for recieving 30 | private int _isReceiving = 0; 31 | #endregion 32 | 33 | #region Constructors 34 | /// 35 | /// new 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// socket is null 41 | /// host is null 42 | public DefaultConnection(long connectionID, Socket socket, IHost host) 43 | { 44 | if (socket == null) throw new ArgumentNullException("socket"); 45 | if (host == null) throw new ArgumentNullException("host"); 46 | 47 | this.ConnectionID = connectionID; 48 | this._socket = socket; 49 | this._host = host; 50 | this._messageBufferSize = host.MessageBufferSize; 51 | 52 | try//fuck... 53 | { 54 | this.LocalEndPoint = (IPEndPoint)socket.LocalEndPoint; 55 | this.RemoteEndPoint = (IPEndPoint)socket.RemoteEndPoint; 56 | } 57 | catch (Exception ex) { Log.Trace.Error("get socket endPoint error.", ex); } 58 | 59 | //init for send... 60 | this._saeSend = host.GetSocketAsyncEventArgs(); 61 | this._saeSend.Completed += new EventHandler(this.SendAsyncCompleted); 62 | this._sendQueue = new SendQueue(); 63 | 64 | //init for receive... 65 | this._saeReceive = host.GetSocketAsyncEventArgs(); 66 | this._saeReceive.Completed += new EventHandler(this.ReceiveAsyncCompleted); 67 | } 68 | #endregion 69 | 70 | #region IConnection Members 71 | /// 72 | /// packet start sending event 73 | /// 74 | public event StartSendingHandler StartSending; 75 | /// 76 | /// packet send callback event 77 | /// 78 | public event SendCallbackHandler SendCallback; 79 | /// 80 | /// message received event 81 | /// 82 | public event MessageReceivedHandler MessageReceived; 83 | /// 84 | /// 连接断开事件 85 | /// 86 | public event DisconnectedHandler Disconnected; 87 | /// 88 | /// connection error event 89 | /// 90 | public event ErrorHandler Error; 91 | 92 | /// 93 | /// return the connection is active. 94 | /// 95 | public bool Active { get { return Thread.VolatileRead(ref this._active) == 1; } } 96 | /// 97 | /// get the connection id. 98 | /// 99 | public long ConnectionID { get; private set; } 100 | /// 101 | /// 获取本地IP地址 102 | /// 103 | public IPEndPoint LocalEndPoint { get; private set; } 104 | /// 105 | /// 获取远程IP地址 106 | /// 107 | public IPEndPoint RemoteEndPoint { get; private set; } 108 | /// 109 | /// 获取或设置与用户数据 110 | /// 111 | public object UserData { get; set; } 112 | /// 113 | /// 获取或设置编码器 114 | /// 115 | public IEncoder Encoder { get; set; } 116 | /// 117 | /// 异步发送数据 118 | /// 119 | /// 120 | public void BeginSend(Packet packet) 121 | { 122 | this.SendPacketInternal(packet); 123 | } 124 | /// 125 | /// 异步接收数据 126 | /// 127 | public void BeginReceive() 128 | { 129 | if (Interlocked.CompareExchange(ref this._isReceiving, 1, 0) == 0) this.ReceiveInternal(this._saeReceive); 130 | } 131 | /// 132 | /// 异步断开连接 133 | /// 134 | /// 135 | public void BeginDisconnect(Exception ex = null) 136 | { 137 | if (Interlocked.CompareExchange(ref this._active, 0, 1) == 1) this.DisconnectInternal(ex); 138 | } 139 | #endregion 140 | 141 | #region Protected Methods 142 | /// 143 | /// dispose 144 | /// 145 | protected virtual void Free() 146 | { 147 | var arrPacket = this._sendQueue.Close(); 148 | this._sendQueue = null; 149 | if (arrPacket != null && arrPacket.Length > 0) 150 | { 151 | foreach (var packet in arrPacket) 152 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); 153 | } 154 | 155 | this._saeSend.Completed -= new EventHandler(this.SendAsyncCompleted); 156 | this._saeSend.UserToken = null; 157 | this._host.ReleaseSocketAsyncEventArgs(this._saeSend); 158 | this._saeSend = null; 159 | 160 | this._saeReceive.Completed -= new EventHandler(this.ReceiveAsyncCompleted); 161 | this._saeReceive.UserToken = null; 162 | this._host.ReleaseSocketAsyncEventArgs(this._saeReceive); 163 | this._saeReceive = null; 164 | 165 | this._socket = null; 166 | this._host = null; 167 | } 168 | #endregion 169 | 170 | #region Private Methods 171 | 172 | #region Fire Events 173 | /// 174 | /// fire StartSending 175 | /// 176 | /// 177 | private void OnStartSending(Packet packet) 178 | { 179 | if (this.StartSending != null) this.StartSending(this, packet); 180 | } 181 | /// 182 | /// fire SendCallback 183 | /// 184 | /// 185 | private void OnSendCallback(SendCallbackEventArgs e) 186 | { 187 | if (e.Status != SendCallbackStatus.Success) e.Packet.SentSize = 0; 188 | if (this.SendCallback != null) this.SendCallback(this, e); 189 | } 190 | /// 191 | /// fire MessageReceived 192 | /// 193 | /// 194 | private void OnMessageReceived(MessageReceivedEventArgs e) 195 | { 196 | if (this.MessageReceived != null) this.MessageReceived(this, e); 197 | } 198 | /// 199 | /// fire Disconnected 200 | /// 201 | private void OnDisconnected(Exception ex) 202 | { 203 | if (this.Disconnected != null) this.Disconnected(this, ex); 204 | } 205 | /// 206 | /// fire Error 207 | /// 208 | /// 209 | private void OnError(Exception ex) 210 | { 211 | if (this.Error != null) this.Error(this, ex); 212 | } 213 | #endregion 214 | 215 | #region Send 216 | /// 217 | /// internal send packet. 218 | /// 219 | /// 220 | /// packet is null 221 | private void SendPacketInternal(Packet packet) 222 | { 223 | var e = this._saeSend; 224 | var queue = this._sendQueue; 225 | if (!this.Active || e == null || queue == null) 226 | { 227 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); return; 228 | } 229 | 230 | switch (queue.TrySend(packet)) 231 | { 232 | case SendResult.Closed: 233 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); break; 234 | case SendResult.SendCurr: 235 | this.OnStartSending(packet); 236 | this.SendPacketInternal(packet, e); 237 | break; 238 | } 239 | } 240 | /// 241 | /// internal send packet. 242 | /// 243 | /// 244 | /// 245 | private void SendPacketInternal(Packet packet, SocketAsyncEventArgs e) 246 | { 247 | this._currSendingPacket = packet; 248 | 249 | //按_messageBufferSize大小分块传输 250 | var length = Math.Min(packet.Payload.Length - packet.SentSize, this._messageBufferSize); 251 | 252 | var completedAsync = true; 253 | try 254 | { 255 | //copy data to send buffer 256 | Buffer.BlockCopy(packet.Payload, packet.SentSize, e.Buffer, 0, length); 257 | e.SetBuffer(0, length); 258 | completedAsync = this._socket.SendAsync(e); 259 | } 260 | catch (Exception ex) 261 | { 262 | this.BeginDisconnect(ex); 263 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); 264 | this.OnError(ex); 265 | } 266 | 267 | if (!completedAsync) this.SendAsyncCompleted(this, e); 268 | } 269 | /// 270 | /// async send callback 271 | /// 272 | /// 273 | /// 274 | private void SendAsyncCompleted(object sender, SocketAsyncEventArgs e) 275 | { 276 | var packet = this._currSendingPacket; 277 | if (packet == null) 278 | { 279 | var ex = new Exception(string.Concat("未知的错误, connection state:", 280 | this.Active.ToString(), 281 | " conectionID:", 282 | this.ConnectionID.ToString(), 283 | " remote address:", 284 | this.RemoteEndPoint.ToString())); 285 | this.OnError(ex); 286 | this.BeginDisconnect(ex); 287 | return; 288 | } 289 | 290 | //send error! 291 | if (e.SocketError != SocketError.Success) 292 | { 293 | this.BeginDisconnect(new SocketException((int)e.SocketError)); 294 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); 295 | return; 296 | } 297 | 298 | packet.SentSize += e.BytesTransferred; 299 | 300 | if (e.Offset + e.BytesTransferred < e.Count) 301 | { 302 | //continue to send until all bytes are sent! 303 | var completedAsync = true; 304 | try 305 | { 306 | e.SetBuffer(e.Offset + e.BytesTransferred, e.Count - e.BytesTransferred - e.Offset); 307 | completedAsync = this._socket.SendAsync(e); 308 | } 309 | catch (Exception ex) 310 | { 311 | this.BeginDisconnect(ex); 312 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Failed)); 313 | this.OnError(ex); 314 | } 315 | 316 | if (!completedAsync) this.SendAsyncCompleted(sender, e); 317 | } 318 | else 319 | { 320 | if (packet.IsSent()) 321 | { 322 | this._currSendingPacket = null; 323 | this.OnSendCallback(new SendCallbackEventArgs(packet, SendCallbackStatus.Success)); 324 | 325 | //send next packet 326 | var queue = this._sendQueue; 327 | if (this.Active && queue != null) 328 | { 329 | Packet nextPacket = queue.TrySendNext(); 330 | if (nextPacket != null) 331 | { 332 | this.OnStartSending(nextPacket); 333 | this.SendPacketInternal(nextPacket, e); 334 | } 335 | } 336 | } 337 | else this.SendPacketInternal(packet, e);//continue send this packet 338 | } 339 | } 340 | #endregion 341 | 342 | #region Receive 343 | /// 344 | /// receive 345 | /// 346 | /// 347 | private void ReceiveInternal(SocketAsyncEventArgs e) 348 | { 349 | if (!this.Active || e == null) return; 350 | 351 | bool completedAsync = true; 352 | try { completedAsync = this._socket.ReceiveAsync(e); } 353 | catch (Exception ex) 354 | { 355 | this.BeginDisconnect(ex); 356 | this.OnError(ex); 357 | } 358 | 359 | if (!completedAsync) this.ReceiveAsyncCompleted(this, e); 360 | } 361 | /// 362 | /// async receive callback 363 | /// 364 | /// 365 | /// 366 | private void ReceiveAsyncCompleted(object sender, SocketAsyncEventArgs e) 367 | { 368 | if (e.SocketError != SocketError.Success) 369 | { 370 | this.BeginDisconnect(new SocketException((int)e.SocketError)); return; 371 | } 372 | if (e.BytesTransferred < 1) 373 | { 374 | this.BeginDisconnect(); return; 375 | } 376 | 377 | ArraySegment buffer; 378 | var ts = this._tsStream; 379 | if (ts == null || ts.Length == 0) buffer = new ArraySegment(e.Buffer, 0, e.BytesTransferred); 380 | else 381 | { 382 | ts.Write(e.Buffer, 0, e.BytesTransferred); 383 | buffer = new ArraySegment(ts.GetBuffer(), 0, (int)ts.Length); 384 | } 385 | 386 | this.OnMessageReceived(new MessageReceivedEventArgs(buffer, this.MessageProcessCallback)); 387 | } 388 | /// 389 | /// message process callback 390 | /// 391 | /// 392 | /// 393 | /// readlength less than 0 or greater than payload.Count. 394 | private void MessageProcessCallback(ArraySegment payload, int readlength) 395 | { 396 | if (readlength < 0 || readlength > payload.Count) 397 | throw new ArgumentOutOfRangeException("readlength", "readlength less than 0 or greater than payload.Count."); 398 | 399 | var ts = this._tsStream; 400 | if (readlength == 0) 401 | { 402 | if (ts == null) this._tsStream = ts = new MemoryStream(this._messageBufferSize); 403 | else ts.SetLength(0); 404 | 405 | ts.Write(payload.Array, payload.Offset, payload.Count); 406 | this.ReceiveInternal(this._saeReceive); 407 | return; 408 | } 409 | 410 | if (readlength == payload.Count) 411 | { 412 | if (ts != null) ts.SetLength(0); 413 | this.ReceiveInternal(this._saeReceive); 414 | return; 415 | } 416 | 417 | //粘包处理 418 | this.OnMessageReceived(new MessageReceivedEventArgs( 419 | new ArraySegment(payload.Array, payload.Offset + readlength, payload.Count - readlength), 420 | this.MessageProcessCallback)); 421 | } 422 | #endregion 423 | 424 | #region Disconnect 425 | /// 426 | /// disconnect 427 | /// 428 | private void DisconnectInternal(Exception ex) 429 | { 430 | try 431 | { 432 | this._socket.Shutdown(SocketShutdown.Both); 433 | this._socket.BeginDisconnect(false, this.DisconnectCallback, ex); 434 | } 435 | catch (Exception ex2) 436 | { 437 | Log.Trace.Error(ex2.Message, ex2); 438 | this.DisconnectCallback(null); 439 | } 440 | } 441 | /// 442 | /// disconnect callback 443 | /// 444 | /// 445 | private void DisconnectCallback(IAsyncResult result) 446 | { 447 | if (result != null) 448 | { 449 | try 450 | { 451 | this._socket.EndDisconnect(result); 452 | this._socket.Close(); 453 | } 454 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 455 | } 456 | 457 | //fire disconnected. 458 | this.OnDisconnected(result == null ? null : result.AsyncState as Exception); 459 | 460 | this.Free(); 461 | } 462 | #endregion 463 | 464 | #endregion 465 | 466 | #region Private Class 467 | /// 468 | /// packet send queue 469 | /// 470 | private class SendQueue 471 | { 472 | #region Private Members 473 | private bool _isSending = false, _isClosed = false; 474 | private readonly Queue _queue = new Queue(); 475 | #endregion 476 | 477 | #region Public Methods 478 | /// 479 | /// try send 480 | /// 481 | /// 482 | /// 483 | public SendResult TrySend(Packet packet) 484 | { 485 | lock (this) 486 | { 487 | if (this._isClosed) return SendResult.Closed; 488 | 489 | if (this._isSending) 490 | { 491 | if (this._queue.Count < 5000) 492 | { 493 | this._queue.Enqueue(packet); 494 | return SendResult.Enqueued; 495 | } 496 | else 497 | { 498 | Log.Trace.Error("queue full",new Exception("queue full")); 499 | } 500 | } 501 | else 502 | { 503 | this._isSending = true; 504 | return SendResult.SendCurr; 505 | } 506 | } 507 | 508 | Thread.Sleep(1); 509 | return this.TrySend(packet); 510 | } 511 | /// 512 | /// try sned next packet 513 | /// 514 | /// 515 | public Packet TrySendNext() 516 | { 517 | lock (this) 518 | { 519 | if (this._queue.Count == 0) 520 | { 521 | this._isSending = false; 522 | return null; 523 | } 524 | 525 | this._isSending = true; 526 | return this._queue.Dequeue(); 527 | } 528 | } 529 | /// 530 | /// close 531 | /// 532 | /// 533 | public Packet[] Close() 534 | { 535 | lock (this) 536 | { 537 | if (this._isClosed) return null; 538 | this._isClosed = true; 539 | 540 | var packets = this._queue.ToArray(); 541 | this._queue.Clear(); 542 | return packets; 543 | } 544 | } 545 | #endregion 546 | } 547 | 548 | /// 549 | /// send result 550 | /// 551 | private enum SendResult : byte 552 | { 553 | /// 554 | /// closed 555 | /// 556 | Closed = 1, 557 | /// 558 | /// send current 559 | /// 560 | SendCurr = 2, 561 | /// 562 | /// 已入列 563 | /// 564 | Enqueued = 3 565 | } 566 | #endregion 567 | 568 | 569 | 570 | } 571 | } -------------------------------------------------------------------------------- /FastNetwork/Event/DisconnectedHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Event 4 | { 5 | /// 6 | /// connection disconnected delegate 7 | /// 8 | /// 9 | /// 10 | public delegate void DisconnectedHandler(IConnection connection, Exception ex); 11 | } -------------------------------------------------------------------------------- /FastNetwork/Event/ErrorHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Event 4 | { 5 | /// 6 | /// error delegate 7 | /// 8 | /// 9 | /// 10 | public delegate void ErrorHandler(IConnection connection, Exception ex); 11 | } -------------------------------------------------------------------------------- /FastNetwork/Event/MessageReceivedHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Event 4 | { 5 | /// 6 | /// message received delegate 7 | /// 8 | /// 9 | /// 10 | public delegate void MessageReceivedHandler(IConnection connection, MessageReceivedEventArgs e); 11 | /// 12 | /// 消息处理handler 13 | /// 14 | /// 15 | /// 16 | public delegate void MessageProcessHandler(ArraySegment buffer, int readlength); 17 | 18 | /// 19 | /// message received eventArgs 20 | /// 21 | public sealed class MessageReceivedEventArgs 22 | { 23 | #region Members 24 | private readonly MessageProcessHandler _processCallback = null; 25 | /// 26 | /// Buffer 27 | /// 28 | public readonly ArraySegment Buffer; 29 | #endregion 30 | 31 | #region Constructors 32 | /// 33 | /// new 34 | /// 35 | /// 36 | /// 37 | /// processCallback is null 38 | public MessageReceivedEventArgs(ArraySegment buffer, MessageProcessHandler processCallback) 39 | { 40 | if (processCallback == null) throw new ArgumentNullException("processCallback"); 41 | this.Buffer = buffer; 42 | this._processCallback = processCallback; 43 | } 44 | #endregion 45 | 46 | #region Public Methods 47 | /// 48 | /// 设置已读取长度 49 | /// 50 | /// 51 | public void SetReadlength(int readlength) 52 | { 53 | this._processCallback(this.Buffer, readlength); 54 | } 55 | #endregion 56 | } 57 | } -------------------------------------------------------------------------------- /FastNetwork/Event/SendCallbackHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Event 4 | { 5 | /// 6 | /// send callback delegate 7 | /// 8 | /// 9 | /// 10 | public delegate void SendCallbackHandler(IConnection connection, SendCallbackEventArgs e); 11 | 12 | /// 13 | /// send callback eventArgs 14 | /// 15 | public sealed class SendCallbackEventArgs 16 | { 17 | #region Public Members 18 | /// 19 | /// packet 20 | /// 21 | public readonly Packet Packet; 22 | /// 23 | /// 状态 24 | /// 25 | public readonly SendCallbackStatus Status; 26 | #endregion 27 | 28 | #region Constructors 29 | /// 30 | /// new 31 | /// 32 | /// 33 | /// 34 | /// packet is null 35 | public SendCallbackEventArgs(Packet packet, SendCallbackStatus status) 36 | { 37 | if (packet == null) throw new ArgumentNullException("packet"); 38 | this.Packet = packet; 39 | this.Status = status; 40 | } 41 | #endregion 42 | } 43 | 44 | /// 45 | /// packet send status 46 | /// 47 | public enum SendCallbackStatus : byte 48 | { 49 | /// 50 | /// 发送成功 51 | /// 52 | Success = 1, 53 | /// 54 | /// 发送失败 55 | /// 56 | Failed = 2 57 | } 58 | } -------------------------------------------------------------------------------- /FastNetwork/Event/StartSendingHandler.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace FastNetwork.Event 3 | { 4 | /// 5 | /// begin send handler 6 | /// 7 | /// 8 | /// 9 | public delegate void StartSendingHandler(IConnection connection, Packet packet); 10 | } -------------------------------------------------------------------------------- /FastNetwork/FastNetwork.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EAEF8B76-66B2-4502-88DE-19D80F016A6B} 8 | Library 9 | Properties 10 | FastNetwork 11 | FastNetwork 12 | v4.0 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | -------------------------------------------------------------------------------- /FastNetwork/IConnection.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Net; 5 | 6 | namespace FastNetwork 7 | { 8 | /// 9 | /// a connection interface. 10 | /// 11 | public interface IConnection 12 | { 13 | /// 14 | /// packet start sending event 15 | /// 16 | event StartSendingHandler StartSending; 17 | /// 18 | /// packet send callback event 19 | /// 20 | event SendCallbackHandler SendCallback; 21 | /// 22 | /// message received event 23 | /// 24 | event MessageReceivedHandler MessageReceived; 25 | /// 26 | /// disconnected event 27 | /// 28 | event DisconnectedHandler Disconnected; 29 | /// 30 | /// connection error event 31 | /// 32 | event ErrorHandler Error; 33 | 34 | /// 35 | /// return the connection is active. 36 | /// 37 | bool Active { get; } 38 | /// 39 | /// get the connection id. 40 | /// 41 | long ConnectionID { get; } 42 | /// 43 | /// 获取本地IP地址 44 | /// 45 | IPEndPoint LocalEndPoint { get; } 46 | /// 47 | /// 获取远程IP地址 48 | /// 49 | IPEndPoint RemoteEndPoint { get; } 50 | /// 51 | /// 获取或设置与用户数据 52 | /// 53 | object UserData { get; set; } 54 | 55 | /// 56 | /// 获取或设置编码器 57 | /// 58 | IEncoder Encoder { get; set; } 59 | 60 | /// 61 | /// 异步发送数据 62 | /// 63 | /// 64 | void BeginSend(Packet packet); 65 | 66 | /// 67 | /// 异步接收数据 68 | /// 69 | void BeginReceive(); 70 | /// 71 | /// 异步断开连接 72 | /// 73 | /// 74 | void BeginDisconnect(Exception ex = null); 75 | } 76 | } -------------------------------------------------------------------------------- /FastNetwork/IHost.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace FastNetwork 3 | { 4 | /// 5 | /// socket connection host interface 6 | /// 7 | public interface IHost : ISAEAPool 8 | { 9 | /// 10 | /// get socket buffer size 11 | /// 12 | int SocketBufferSize { get; } 13 | /// 14 | /// get message buffer size 15 | /// 16 | int MessageBufferSize { get; } 17 | 18 | /// 19 | /// 生成下一个连接ID 20 | /// 21 | /// 22 | long NextConnectionID(); 23 | /// 24 | /// get by connectionID 25 | /// 26 | /// 27 | /// 28 | IConnection GetConnectionByID(long connectionID); 29 | 30 | /// 31 | /// 启动 32 | /// 33 | void Start(); 34 | /// 35 | /// 停止 36 | /// 37 | void Stop(); 38 | } 39 | } -------------------------------------------------------------------------------- /FastNetwork/ISAEAPool.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | 3 | namespace FastNetwork 4 | { 5 | /// 6 | /// socketAsyncEventArgs pool interface 7 | /// 8 | public interface ISAEAPool 9 | { 10 | /// 11 | /// get 12 | /// 13 | /// 14 | SocketAsyncEventArgs GetSocketAsyncEventArgs(); 15 | /// 16 | /// release 17 | /// 18 | /// 19 | void ReleaseSocketAsyncEventArgs(SocketAsyncEventArgs e); 20 | } 21 | } -------------------------------------------------------------------------------- /FastNetwork/IServerHandler.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | 5 | namespace FastNetwork 6 | { 7 | /// 8 | /// 提供出来的处理函数接口 9 | /// 10 | /// 11 | public interface IServerHandler 12 | { 13 | /// 14 | /// 当建立socket连接时,会调用此方法 15 | /// 16 | /// 17 | void OnConnected(IConnection connection); 18 | /// 19 | /// 开始发送 20 | /// 21 | /// 22 | /// 23 | void OnStartSending(IConnection connection, Packet packet); 24 | /// 25 | /// 发送回调 26 | /// 27 | /// 28 | /// 29 | void OnSendCallback(IConnection connection, SendCallbackEventArgs e); 30 | /// 31 | /// 当接收到客户端新消息时,会调用此方法. 32 | /// 33 | /// 34 | /// 35 | void OnReceived(IConnection connection, Object obj); 36 | /// 37 | /// 当socket连接断开时,会调用此方法 38 | /// 39 | /// 40 | /// 41 | void OnDisconnected(IConnection connection, Exception ex); 42 | /// 43 | /// 当发生异常时,会调用此方法 44 | /// 45 | /// 46 | /// 47 | void OnException(IConnection connection, Exception ex); 48 | } 49 | } -------------------------------------------------------------------------------- /FastNetwork/ISocketListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace FastNetwork 5 | { 6 | /// 7 | /// socket listener 8 | /// 9 | public interface ISocketListener 10 | { 11 | /// 12 | /// socket accepted event 13 | /// 14 | event Action Accepted; 15 | 16 | /// 17 | /// get name 18 | /// 19 | string Name { get; } 20 | /// 21 | /// get endpoint 22 | /// 23 | EndPoint EndPoint { get; } 24 | /// 25 | /// start listen 26 | /// 27 | void Start(); 28 | /// 29 | /// stop listen 30 | /// 31 | void Stop(); 32 | } 33 | } -------------------------------------------------------------------------------- /FastNetwork/IUdpServer.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace FastNetwork 4 | { 5 | /// 6 | /// upd server interface 7 | /// 8 | public interface IUdpServer 9 | { 10 | /// 11 | /// 开始 12 | /// 13 | void Start(); 14 | /// 15 | /// stop 16 | /// 17 | void Stop(); 18 | /// 19 | /// 异步发送 20 | /// 21 | /// 22 | /// 23 | void SendTo(EndPoint endPoint, byte[] payload); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /FastNetwork/IUdpServerHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork 4 | { 5 | /// 6 | /// udp service interface. 7 | /// 8 | /// 9 | public interface IUdpServerHandler 10 | { 11 | /// 12 | /// OnReceived 13 | /// 14 | /// 15 | /// 16 | void OnReceived(UdpSession session, Object obj); 17 | /// 18 | /// OnError 19 | /// 20 | /// 21 | /// 22 | void OnError(UdpSession session, Exception ex); 23 | } 24 | } -------------------------------------------------------------------------------- /FastNetwork/Log/ConsoleListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Log 4 | { 5 | /// 6 | /// console trace listener 7 | /// 8 | public sealed class ConsoleListener : ITraceListener 9 | { 10 | /// 11 | /// debug 12 | /// 13 | /// 14 | public void Debug(string message) 15 | { 16 | Console.WriteLine(string.Concat(message, Environment.NewLine)); 17 | } 18 | /// 19 | /// error 20 | /// 21 | /// 22 | /// 23 | public void Error(string message, Exception ex) 24 | { 25 | Console.WriteLine(string.Concat(message, Environment.NewLine, ex.ToString(), Environment.NewLine)); 26 | } 27 | /// 28 | /// info 29 | /// 30 | /// 31 | public void Info(string message) 32 | { 33 | Console.WriteLine(string.Concat(message, Environment.NewLine)); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /FastNetwork/Log/DiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Log 4 | { 5 | /// 6 | /// diagnostic listener 7 | /// 8 | public sealed class DiagnosticListener : ITraceListener 9 | { 10 | /// 11 | /// debug 12 | /// 13 | /// 14 | public void Debug(string message) 15 | { 16 | System.Diagnostics.Trace.WriteLine(message); 17 | } 18 | /// 19 | /// error 20 | /// 21 | /// 22 | /// 23 | public void Error(string message, Exception ex) 24 | { 25 | System.Diagnostics.Trace.TraceError(ex.ToString()); 26 | } 27 | /// 28 | /// info 29 | /// 30 | /// 31 | public void Info(string message) 32 | { 33 | System.Diagnostics.Trace.TraceInformation(message); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /FastNetwork/Log/ITraceListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Log 4 | { 5 | /// 6 | /// trace listener interface. 7 | /// 8 | public interface ITraceListener 9 | { 10 | /// 11 | /// debug 12 | /// 13 | /// 14 | void Debug(string message); 15 | /// 16 | /// error 17 | /// 18 | /// 19 | /// 20 | void Error(string message, Exception ex); 21 | /// 22 | /// info 23 | /// 24 | /// 25 | void Info(string message); 26 | } 27 | } -------------------------------------------------------------------------------- /FastNetwork/Log/ListenerWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Log 4 | { 5 | /// 6 | /// trace listener wrapper 7 | /// 8 | public sealed class ListenerWrapper : ITraceListener 9 | { 10 | private readonly Action _onDebug = null; 11 | private readonly Action _onError = null; 12 | private readonly Action _onInfo = null; 13 | 14 | /// 15 | /// new 16 | /// 17 | /// 18 | /// 19 | /// 20 | public ListenerWrapper(Action onDebug, Action onError, Action onInfo) 21 | { 22 | if (onDebug == null) throw new ArgumentNullException("onDebug"); 23 | if (onError == null) throw new ArgumentNullException("onError"); 24 | if (onInfo == null) throw new ArgumentNullException("onInfo"); 25 | 26 | this._onDebug = onDebug; 27 | this._onError = onError; 28 | this._onInfo = onInfo; 29 | } 30 | 31 | /// 32 | /// debug 33 | /// 34 | /// 35 | public void Debug(string message) 36 | { 37 | this._onDebug(message); 38 | } 39 | /// 40 | /// error 41 | /// 42 | /// 43 | /// 44 | public void Error(string message, Exception ex) 45 | { 46 | this._onError(message, ex); 47 | } 48 | /// 49 | /// info 50 | /// 51 | /// 52 | public void Info(string message) 53 | { 54 | this._onInfo(message); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /FastNetwork/Log/Trace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FastNetwork.Log 5 | { 6 | /// 7 | /// trace 8 | /// 9 | static public class Trace 10 | { 11 | static private readonly List _list = new List(); 12 | 13 | /// 14 | /// enable console trace listener 15 | /// 16 | static public void EnableConsole() 17 | { 18 | _list.Add(new ConsoleListener()); 19 | } 20 | /// 21 | /// enable diagnostic 22 | /// 23 | static public void EnableDiagnostic() 24 | { 25 | _list.Add(new DiagnosticListener()); 26 | } 27 | 28 | /// 29 | /// add listener 30 | /// 31 | /// 32 | /// listener is null 33 | static public void AddListener(ITraceListener listener) 34 | { 35 | if (listener == null) throw new ArgumentNullException("listener"); 36 | _list.Add(listener); 37 | } 38 | 39 | /// 40 | /// debug 41 | /// 42 | /// 43 | /// message is null 44 | static public void Debug(string message) 45 | { 46 | if (message == null) throw new ArgumentNullException("message"); 47 | _list.ForEach(c => c.Debug(message)); 48 | } 49 | /// 50 | /// info 51 | /// 52 | /// 53 | /// message is null 54 | static public void Info(string message) 55 | { 56 | if (message == null) throw new ArgumentNullException("message"); 57 | _list.ForEach(c => c.Info(message)); 58 | } 59 | /// 60 | /// error 61 | /// 62 | /// 63 | /// 64 | /// message is null 65 | static public void Error(string message, Exception ex) 66 | { 67 | if (message == null) throw new ArgumentNullException("message"); 68 | _list.ForEach(c => c.Error(message, ex)); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /FastNetwork/Packet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork 4 | { 5 | /// 6 | /// packet 7 | /// 8 | public class Packet 9 | { 10 | #region Members 11 | /// 12 | /// get or set sent size. 13 | /// 14 | internal int SentSize = 0; 15 | /// 16 | /// get begin time 17 | /// 18 | public readonly DateTime BeginTime = DateTime.UtcNow; 19 | /// 20 | /// get payload 21 | /// 22 | public readonly byte[] Payload; 23 | #endregion 24 | 25 | #region Constructors 26 | /// 27 | /// new 28 | /// 29 | /// 30 | /// payload is null. 31 | public Packet(byte[] payload) 32 | { 33 | if (payload == null) throw new ArgumentNullException("payload"); 34 | this.Payload = payload; 35 | } 36 | #endregion 37 | 38 | #region Public Properties 39 | /// 40 | /// get or set tag object 41 | /// 42 | public object Tag { get; set; } 43 | #endregion 44 | 45 | #region Public Methods 46 | /// 47 | /// 获取一个值,该值指示当前packet是否已发送完毕. 48 | /// 49 | /// true表示已发送完毕 50 | public bool IsSent() 51 | { 52 | return this.SentSize >= this.Payload.Length; 53 | } 54 | #endregion 55 | } 56 | } -------------------------------------------------------------------------------- /FastNetwork/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("FastNetwork")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FastNetwork")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("e4aedc2a-2425-472a-9d22-a868147ea295")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FastNetwork/Protocol/BadProtocolException.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace FastNetwork.Protocol 3 | { 4 | /// 5 | /// bad protocol exception 6 | /// 7 | public sealed class BadProtocolException : System.ApplicationException 8 | { 9 | /// 10 | /// new 11 | /// 12 | public BadProtocolException() 13 | : base("bad protocol.") 14 | { 15 | } 16 | /// 17 | /// new 18 | /// 19 | /// 20 | public BadProtocolException(string message) 21 | : base(message) 22 | { 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /FastNetwork/Protocol/DefaultBinaryProtocol.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Utils; 2 | using System; 3 | using System.Text; 4 | 5 | namespace FastNetwork.Protocol 6 | { 7 | /// 8 | /// 异步二进制协议 9 | /// 协议格式 10 | /// [Message Length(int32)][SeqID(int32)][Body Buffer] 11 | /// 12 | public sealed class DefaultBinaryProtocol : IProtocol 13 | { 14 | #region IProtocol Members 15 | /// 16 | /// find command 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// bad async binary protocl 24 | public ReceivePacket TryToTranslateMessage(IConnection connection, ArraySegment buffer, 25 | int maxMessageSize, out int readlength) 26 | { 27 | if (buffer.Count < 4) { readlength = 0; return null; } 28 | 29 | var payload = buffer.Array; 30 | 31 | //获取message length 32 | var messageLength = Utils.NetworkBitConverter.ToInt32(payload, buffer.Offset); 33 | if (messageLength < 4) throw new BadProtocolException("bad async binary protocl"); 34 | if (messageLength > maxMessageSize) throw new BadProtocolException("message is too long"); 35 | 36 | readlength = messageLength + 4; 37 | if (buffer.Count < readlength) 38 | { 39 | readlength = 0; return null; 40 | } 41 | byte[] data = null; 42 | if (messageLength > 0) 43 | { 44 | data = new byte[messageLength]; 45 | Buffer.BlockCopy(payload, buffer.Offset + 4, data, 0, messageLength); 46 | } 47 | //TODO 如何返回一个数据 48 | return new ReceivePacket(data); 49 | } 50 | #endregion 51 | } 52 | } -------------------------------------------------------------------------------- /FastNetwork/Protocol/IDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork.Protocol 7 | { 8 | public interface IDecoder 9 | { 10 | Object decode(IConnection connection, byte[] buffer); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FastNetwork/Protocol/IEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork.Protocol 7 | { 8 | public interface IEncoder 9 | { 10 | 11 | byte[] encode(IConnection connection, Object msg); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /FastNetwork/Protocol/IProtocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Protocol 4 | { 5 | /// 6 | /// 协议接口 7 | /// 8 | /// 9 | public interface IProtocol 10 | { 11 | /// 12 | /// Find CommandInfo 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | ReceivePacket TryToTranslateMessage(IConnection connection, ArraySegment buffer, 20 | int maxMessageSize, out int readlength); 21 | } 22 | } -------------------------------------------------------------------------------- /FastNetwork/Protocol/IUdpProtocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace FastNetwork.Protocol 5 | { 6 | /// 7 | /// a upd protocol 8 | /// 9 | /// 10 | public interface IUdpProtocol 11 | { 12 | /// 13 | /// find command info 14 | /// 15 | /// 16 | /// 17 | Object FindCommandInfo(ArraySegment buffer); 18 | } 19 | } -------------------------------------------------------------------------------- /FastNetwork/Protocol/PacketBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork.Protocol 7 | { 8 | static public class PacketBuilder 9 | { 10 | 11 | #region ToAsyncBinary 12 | /// 13 | /// to async binary 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | static public Packet ToAsyncBinary(byte[] buffer) 20 | { 21 | var messageLength = (buffer == null ? 0 : buffer.Length) + 4; 22 | var sendBuffer = new byte[messageLength + 4]; 23 | 24 | //write message length 25 | Buffer.BlockCopy(Utils.NetworkBitConverter.GetBytes(messageLength), 0, sendBuffer, 0, 4); 26 | //write body buffer 27 | if (buffer != null && buffer.Length > 0) 28 | Buffer.BlockCopy(buffer, 0, sendBuffer, 4, buffer.Length); 29 | 30 | return new Packet(sendBuffer); 31 | } 32 | 33 | static public byte[] ToAsyncBinaryByte(byte[] buffer) 34 | { 35 | var messageLength = (buffer == null ? 0 : buffer.Length) + 4; 36 | var sendBuffer = new byte[messageLength + 4]; 37 | 38 | //write message length 39 | Buffer.BlockCopy(Utils.NetworkBitConverter.GetBytes(messageLength), 0, sendBuffer, 0, 4); 40 | //write body buffer 41 | if (buffer != null && buffer.Length > 0) 42 | Buffer.BlockCopy(buffer, 0, sendBuffer, 4, buffer.Length); 43 | 44 | return sendBuffer; 45 | } 46 | #endregion 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /FastNetwork/ReceivePacket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork 7 | { 8 | /// 9 | /// 表示收到的完整的一个消息 10 | /// 11 | public class ReceivePacket 12 | { 13 | 14 | public ReceivePacket(byte[] data) 15 | { 16 | this.Buffer = data; 17 | } 18 | 19 | #region Public Properties 20 | /// 21 | /// 主体内容 22 | /// 23 | public byte[] Buffer 24 | { 25 | get; 26 | private set; 27 | } 28 | #endregion 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /FastNetwork/SocketConnector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | 5 | namespace FastNetwork 6 | { 7 | /// 8 | /// 连接器 9 | /// 10 | public sealed class SocketConnector 11 | { 12 | #region Members 13 | /// 14 | /// get node name 15 | /// 16 | public readonly string Name; 17 | /// 18 | /// get node endpoint 19 | /// 20 | private readonly EndPoint EndPoint; 21 | /// 22 | /// get node owner host 23 | /// 24 | private readonly IHost Host = null; 25 | 26 | private Action _onConnected; 27 | private Action _onDisconnected; 28 | private volatile bool _isStop = false; 29 | #endregion 30 | 31 | #region Constructors 32 | /// 33 | /// new 34 | /// 35 | /// 36 | /// 37 | /// 38 | /// 39 | /// 40 | public SocketConnector(string name, 41 | EndPoint endPoint, 42 | IHost host, 43 | Action onConnected, 44 | Action onDisconnected) 45 | { 46 | this.Name = name; 47 | this.EndPoint = endPoint; 48 | this.Host = host; 49 | this._onConnected = onConnected; 50 | this._onDisconnected = onDisconnected; 51 | } 52 | #endregion 53 | 54 | #region Public Methods 55 | /// 56 | /// start 57 | /// 58 | public void Start() 59 | { 60 | BeginConnect(this.EndPoint, this.Host, connection => 61 | { 62 | if (this._isStop) 63 | { 64 | if (connection != null) connection.BeginDisconnect(); return; 65 | } 66 | if (connection == null) 67 | { 68 | Utils.TaskEx.Delay(new Random().Next(1500, 3000), this.Start); return; 69 | } 70 | connection.Disconnected += this.OnDisconnected; 71 | this._onConnected(connection); 72 | }); 73 | } 74 | /// 75 | /// stop 76 | /// 77 | public void Stop() 78 | { 79 | this._isStop = true; 80 | } 81 | #endregion 82 | 83 | #region Private Methods 84 | /// 85 | /// 断开连接 86 | /// 87 | /// 88 | /// 89 | private void OnDisconnected(IConnection connection, Exception ex) 90 | { 91 | connection.Disconnected -= this.OnDisconnected; 92 | //delay reconnect 20ms ~ 200ms 93 | if (!this._isStop) Utils.TaskEx.Delay(new Random().Next(20, 200), this.Start); 94 | //fire disconnected event 95 | this._onDisconnected(connection,ex); 96 | } 97 | #endregion 98 | 99 | #region Static Methods 100 | /// 101 | /// begin connect 102 | /// 103 | /// 104 | /// 105 | /// 106 | /// endPoint is null 107 | /// host is null 108 | /// callback is null 109 | static public void BeginConnect(EndPoint endPoint, IHost host, Action callback) 110 | { 111 | if (endPoint == null) throw new ArgumentNullException("endPoint"); 112 | if (host == null) throw new ArgumentNullException("host"); 113 | if (callback == null) throw new ArgumentNullException("callback"); 114 | 115 | Log.Trace.Debug(string.Concat("begin connect to ", endPoint.ToString())); 116 | 117 | var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 118 | try 119 | { 120 | socket.BeginConnect(endPoint, ar => 121 | { 122 | try 123 | { 124 | socket.EndConnect(ar); 125 | socket.NoDelay = true; 126 | socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); 127 | socket.ReceiveBufferSize = host.SocketBufferSize; 128 | socket.SendBufferSize = host.SocketBufferSize; 129 | } 130 | catch (Exception ex) 131 | { 132 | try 133 | { 134 | socket.Close(); 135 | socket.Dispose(); 136 | } 137 | catch { } 138 | 139 | Log.Trace.Error(ex.Message, ex); 140 | callback(null); return; 141 | } 142 | 143 | callback(new DefaultConnection(host.NextConnectionID(), socket, host)); 144 | }, null); 145 | } 146 | catch (Exception ex) 147 | { 148 | Log.Trace.Error(ex.Message, ex); 149 | callback(null); 150 | } 151 | } 152 | #endregion 153 | } 154 | } -------------------------------------------------------------------------------- /FastNetwork/SocketListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | 5 | namespace FastNetwork 6 | { 7 | /// 8 | /// socket listener 9 | /// 10 | public sealed class SocketListener : ISocketListener 11 | { 12 | #region Private Members 13 | private readonly IHost _host = null; 14 | private const int BACKLOG = 100; 15 | private Socket _socket = null; 16 | private readonly SocketAsyncEventArgs _ae = null; 17 | #endregion 18 | 19 | #region Constructors 20 | /// 21 | /// new 22 | /// 23 | /// 24 | /// 25 | /// 26 | /// name is null or empty 27 | /// endPoint is null 28 | /// host is null 29 | public SocketListener(string name, IPEndPoint endPoint, IHost host) 30 | { 31 | if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name"); 32 | if (endPoint == null) throw new ArgumentNullException("endPoint"); 33 | if (host == null) throw new ArgumentNullException("host"); 34 | 35 | this.Name = name; 36 | this.EndPoint = endPoint; 37 | this._host = host; 38 | 39 | this._ae = new SocketAsyncEventArgs(); 40 | this._ae.Completed += new EventHandler(this.AcceptAsyncCompleted); 41 | } 42 | #endregion 43 | 44 | #region ISocketListener Members 45 | /// 46 | /// socket accepted event 47 | /// 48 | public event Action Accepted; 49 | /// 50 | /// get listener name 51 | /// 52 | public string Name 53 | { 54 | get; 55 | private set; 56 | } 57 | /// 58 | /// get listener endPoint 59 | /// 60 | public EndPoint EndPoint 61 | { 62 | get; 63 | private set; 64 | } 65 | /// 66 | /// start 67 | /// 68 | public void Start() 69 | { 70 | if (this._socket == null) 71 | { 72 | this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 73 | this._socket.Bind(this.EndPoint); 74 | this._socket.Listen(BACKLOG); 75 | 76 | this.AcceptAsync(this._socket); 77 | } 78 | } 79 | /// 80 | /// stop 81 | /// 82 | public void Stop() 83 | { 84 | if (this._socket != null) 85 | { 86 | this._socket.Close(); 87 | this._socket = null; 88 | } 89 | } 90 | #endregion 91 | 92 | #region Private Methods 93 | /// 94 | /// accept socket. 95 | /// 96 | /// 97 | private void AcceptAsync(Socket socket) 98 | { 99 | if (socket == null) return; 100 | 101 | bool asyncCompleted = true; 102 | try { asyncCompleted = this._socket.AcceptAsync(this._ae); } 103 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 104 | 105 | if (!asyncCompleted) this.AcceptAsyncCompleted(this, this._ae); 106 | } 107 | /// 108 | /// async accept socket completed handle. 109 | /// 110 | /// 111 | /// 112 | private void AcceptAsyncCompleted(object sender, SocketAsyncEventArgs e) 113 | { 114 | Socket acceptedSocket = null; 115 | if (e.SocketError == SocketError.Success) acceptedSocket = e.AcceptSocket; 116 | e.AcceptSocket = null; 117 | 118 | if (acceptedSocket != null) 119 | { 120 | acceptedSocket.NoDelay = true; 121 | acceptedSocket.ReceiveBufferSize = this._host.SocketBufferSize; 122 | acceptedSocket.SendBufferSize = this._host.SocketBufferSize; 123 | acceptedSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true); 124 | this.Accepted(this, new DefaultConnection(this._host.NextConnectionID(), acceptedSocket, this._host)); 125 | } 126 | 127 | //continue to accept! 128 | this.AcceptAsync(this._socket); 129 | } 130 | #endregion 131 | } 132 | } -------------------------------------------------------------------------------- /FastNetwork/SocketServer.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Event; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Net; 6 | using System.Threading; 7 | 8 | namespace FastNetwork 9 | { 10 | /// 11 | /// socket 服务器 12 | /// 13 | public class SocketServer : BaseSocketServer 14 | { 15 | #region Private Members 16 | private readonly List _listListener = new List(); 17 | private readonly IServerHandler _handler = null; 18 | private readonly IProtocol _protocol = null; 19 | //编码器 20 | private readonly IEncoder _encoder = null; 21 | //解码器 22 | private readonly IDecoder _decoder = null; 23 | private readonly int _maxMessageSize; 24 | private readonly int _maxConnections; 25 | #endregion 26 | 27 | #region Constructors 28 | /// 29 | /// new 30 | /// 31 | /// 32 | /// 33 | /// 34 | /// 35 | /// 36 | /// 37 | /// socketService is null. 38 | /// protocol is null. 39 | /// maxMessageSize 40 | /// maxConnections 41 | public SocketServer(IServerHandler handler, 42 | Protocol.IProtocol protocol, 43 | int socketBufferSize, 44 | int messageBufferSize, 45 | int maxMessageSize, 46 | int maxConnections) 47 | : base(socketBufferSize, messageBufferSize) 48 | { 49 | if (handler == null) throw new ArgumentNullException("handler"); 50 | if (protocol == null) throw new ArgumentNullException("protocol"); 51 | if (maxMessageSize < 1) throw new ArgumentOutOfRangeException("maxMessageSize"); 52 | if (maxConnections < 1) throw new ArgumentOutOfRangeException("maxConnections"); 53 | 54 | this._handler = handler; 55 | this._protocol = protocol; 56 | this._maxMessageSize = maxMessageSize; 57 | this._maxConnections = maxConnections; 58 | } 59 | /// 60 | /// 使用默认配置参数的构造函数 61 | /// 62 | /// 63 | public SocketServer(IServerHandler handler,IEncoder encoder, IDecoder decoder) 64 | : base(DefaultConfigure.SocketBufferSize, DefaultConfigure.MessageBufferSize) 65 | { 66 | if (handler == null) throw new ArgumentNullException("handler"); 67 | if (encoder == null) throw new ArgumentNullException("encoder"); 68 | if (decoder == null) throw new ArgumentNullException("decoder"); 69 | this._handler = handler; 70 | this._protocol = new DefaultBinaryProtocol(); 71 | this._encoder = encoder; 72 | this._decoder = decoder; 73 | this._maxMessageSize = DefaultConfigure.MaxMessageSize; 74 | this._maxConnections = DefaultConfigure.MaxConnections; 75 | } 76 | #endregion 77 | 78 | #region Private Methods 79 | /// 80 | /// socket accepted handler 81 | /// 82 | /// 83 | /// 84 | private void listener_Accepted(ISocketListener listener, IConnection connection) 85 | { 86 | if (base._listConnections.Count() > this._maxConnections) 87 | { 88 | connection.BeginDisconnect(); return; 89 | } 90 | base.RegisterConnection(connection); 91 | } 92 | #endregion 93 | 94 | #region Override Methods 95 | /// 96 | /// start 97 | /// 98 | public override void Start() 99 | { 100 | foreach (var child in this._listListener) child.Start(); 101 | } 102 | /// 103 | /// stop 104 | /// 105 | public override void Stop() 106 | { 107 | foreach (var child in this._listListener) child.Stop(); 108 | base.Stop(); 109 | } 110 | /// 111 | /// add socket listener 112 | /// 113 | /// 114 | /// 115 | /// 116 | public override ISocketListener AddListener(string name, IPEndPoint endPoint) 117 | { 118 | var listener = new SocketListener(name, endPoint, this); 119 | this._listListener.Add(listener); 120 | listener.Accepted += new Action(this.listener_Accepted); 121 | return listener; 122 | } 123 | /// 124 | /// OnConnected 125 | /// 126 | /// 127 | protected override void OnConnected(IConnection connection) 128 | { 129 | //设置连接的编码器 130 | connection.Encoder = this._encoder; 131 | base.OnConnected(connection); 132 | try { this._handler.OnConnected(connection); } 133 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 134 | } 135 | /// 136 | /// start sending 137 | /// 138 | /// 139 | /// 140 | protected override void OnStartSending(IConnection connection, Packet packet) 141 | { 142 | base.OnStartSending(connection, packet); 143 | try { this._handler.OnStartSending(connection, packet); } 144 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 145 | } 146 | /// 147 | /// send callback 148 | /// 149 | /// 150 | /// 151 | protected override void OnSendCallback(IConnection connection, SendCallbackEventArgs e) 152 | { 153 | base.OnSendCallback(connection, e); 154 | try { this._handler.OnSendCallback(connection, e); } 155 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 156 | } 157 | /// 158 | /// OnMessageReceived 159 | /// 160 | /// 161 | /// 162 | protected override void OnMessageReceived(IConnection connection, MessageReceivedEventArgs e) 163 | { 164 | base.OnMessageReceived(connection, e); 165 | 166 | int readlength=0; 167 | ReceivePacket packet = null; 168 | Object obj = null;//解析的对象 169 | try 170 | { 171 | packet = this._protocol.TryToTranslateMessage(connection, e.Buffer, this._maxMessageSize, out readlength); 172 | if (packet == null) 173 | return; 174 | obj = this._decoder.decode(connection, packet.Buffer); 175 | } 176 | catch (Exception ex) 177 | { 178 | this.OnError(connection, ex); 179 | connection.BeginDisconnect(ex); 180 | e.SetReadlength(e.Buffer.Count); 181 | return; 182 | } 183 | 184 | if (packet != null) 185 | ThreadPool.QueueUserWorkItem(_ => 186 | { 187 | try { this._handler.OnReceived(connection, obj); } 188 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 189 | }); 190 | e.SetReadlength(readlength); 191 | } 192 | /// 193 | /// OnDisconnected 194 | /// 195 | /// 196 | /// 197 | protected override void OnDisconnected(IConnection connection, Exception ex) 198 | { 199 | base.OnDisconnected(connection, ex); 200 | try { this._handler.OnDisconnected(connection, ex); } 201 | catch (Exception ex2) { Log.Trace.Error(ex.Message, ex2); } 202 | } 203 | /// 204 | /// onError 205 | /// 206 | /// 207 | /// 208 | protected override void OnError(IConnection connection, Exception ex) 209 | { 210 | base.OnError(connection, ex); 211 | try { this._handler.OnException(connection, ex); } 212 | catch (Exception ex2) { Log.Trace.Error(ex.Message, ex2); } 213 | } 214 | #endregion 215 | } 216 | } -------------------------------------------------------------------------------- /FastNetwork/UdpServer.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Protocol; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | 8 | namespace FastNetwork 9 | { 10 | /// 11 | /// udp 服务器 12 | /// 13 | public sealed class UdpServer : Utils.DisposableBase, IUdpServer 14 | { 15 | #region Private Members 16 | private readonly int _port; 17 | private readonly int _messageBufferSize; 18 | private readonly int _receiveThreads;//接收线程数 19 | 20 | private Socket _socket = null; 21 | private AsyncSendPool _pool = null; 22 | 23 | private readonly IUdpProtocol _protocol = null; 24 | private readonly IUdpServerHandler _handler = null; 25 | #endregion 26 | 27 | #region Constructors 28 | /// 29 | /// new 30 | /// 31 | /// 32 | /// 33 | /// 34 | public UdpServer(int port, IUdpProtocol protocol, 35 | IUdpServerHandler handler) 36 | : this(port, 2048, 1, protocol, handler) 37 | { 38 | } 39 | /// 40 | /// new 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// protocol is null. 49 | /// service is null. 50 | public UdpServer(int port, int messageBufferSize, int receiveThreads, 51 | IUdpProtocol protocol, 52 | IUdpServerHandler handler) 53 | { 54 | if (receiveThreads < 1) throw new ArgumentOutOfRangeException("receiveThreads"); 55 | if (protocol == null) throw new ArgumentNullException("protocol"); 56 | if (handler == null) throw new ArgumentNullException("handler"); 57 | 58 | this._port = port; 59 | this._messageBufferSize = messageBufferSize; 60 | this._receiveThreads = receiveThreads; 61 | this._protocol = protocol; 62 | this._handler = handler; 63 | } 64 | #endregion 65 | 66 | #region Private Methods 67 | /// 68 | /// 异步接收数据 69 | /// 70 | /// 71 | private void BeginReceive(SocketAsyncEventArgs e) 72 | { 73 | if (!this._socket.ReceiveFromAsync(e)) this.ReceiveCompleted(this, e); 74 | } 75 | /// 76 | /// completed handle 77 | /// 78 | /// 79 | /// 80 | private void ReceiveCompleted(object sender, SocketAsyncEventArgs e) 81 | { 82 | if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) 83 | { 84 | Object cmdInfo = null; 85 | 86 | try { cmdInfo = this._protocol.FindCommandInfo(new ArraySegment(e.Buffer, 0, e.BytesTransferred)); } 87 | catch (Exception ex) 88 | { 89 | Log.Trace.Error(ex.Message, ex); 90 | try { this._handler.OnError(new UdpSession(e.RemoteEndPoint, this), ex); } 91 | catch (Exception ex2) {Log.Trace.Error(ex2.Message, ex2); } 92 | } 93 | 94 | if (cmdInfo != null) 95 | { 96 | ThreadPool.QueueUserWorkItem(_ => 97 | { 98 | try { this._handler.OnReceived(new UdpSession(e.RemoteEndPoint, this), cmdInfo); } 99 | catch (Exception ex) 100 | { 101 | Log.Trace.Error(ex.Message, ex); 102 | try { this._handler.OnError(new UdpSession(e.RemoteEndPoint, this), ex); } 103 | catch (Exception ex2) {Log.Trace.Error(ex2.Message, ex2); } 104 | } 105 | }); 106 | } 107 | } 108 | this.BeginReceive(e); 109 | } 110 | #endregion 111 | 112 | #region IUdpServer Members 113 | /// 114 | /// start 115 | /// 116 | public void Start() 117 | { 118 | base.CheckDisposedWithException(); 119 | 120 | this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 121 | this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 122 | this._socket.Bind(new IPEndPoint(IPAddress.Any, this._port)); 123 | this._socket.DontFragment = true; 124 | 125 | this._pool = new AsyncSendPool(this._messageBufferSize, this._socket); 126 | 127 | for (int i = 0; i < this._receiveThreads; i++) 128 | { 129 | var e = new SocketAsyncEventArgs(); 130 | e.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); 131 | e.SetBuffer(new byte[this._messageBufferSize], 0, this._messageBufferSize); 132 | e.Completed += new EventHandler(this.ReceiveCompleted); 133 | this.BeginReceive(e); 134 | } 135 | } 136 | /// 137 | /// stop 138 | /// 139 | public void Stop() 140 | { 141 | base.Dispose(); 142 | } 143 | /// 144 | /// send to... 145 | /// 146 | /// 147 | /// 148 | public void SendTo(EndPoint endPoint, byte[] payload) 149 | { 150 | base.CheckDisposedWithException(); 151 | this._pool.SendAsync(endPoint, payload); 152 | } 153 | #endregion 154 | 155 | #region Override Methods 156 | /// 157 | /// free 158 | /// 159 | /// 160 | protected override void Free(bool disposing) 161 | { 162 | this._socket.Close(); 163 | this._socket = null; 164 | this._pool = null; 165 | } 166 | #endregion 167 | 168 | /// 169 | /// 用于异步发送的对象池 170 | /// 171 | private class AsyncSendPool : ISAEAPool 172 | { 173 | #region Private Members 174 | private const int MAXPOOLSIZE = 3000; 175 | private readonly int _messageBufferSize; 176 | private readonly Socket _socket = null; 177 | private readonly ConcurrentStack _stack = new ConcurrentStack(); 178 | #endregion 179 | 180 | #region Constructors 181 | /// 182 | /// new 183 | /// 184 | /// 185 | /// 186 | public AsyncSendPool(int messageBufferSize, Socket socket) 187 | { 188 | if (socket == null) throw new ArgumentNullException("socket"); 189 | this._messageBufferSize = messageBufferSize; 190 | this._socket = socket; 191 | } 192 | #endregion 193 | 194 | #region ISAEAPool Members 195 | /// 196 | /// get 197 | /// 198 | /// 199 | public SocketAsyncEventArgs GetSocketAsyncEventArgs() 200 | { 201 | SocketAsyncEventArgs e; 202 | if (this._stack.TryPop(out e)) return e; 203 | 204 | e = new SocketAsyncEventArgs(); 205 | e.SetBuffer(new byte[this._messageBufferSize], 0, this._messageBufferSize); 206 | e.Completed += new EventHandler(this.SendCompleted); 207 | return e; 208 | } 209 | /// 210 | /// release 211 | /// 212 | /// 213 | public void ReleaseSocketAsyncEventArgs(SocketAsyncEventArgs e) 214 | { 215 | if (this._stack.Count >= MAXPOOLSIZE) 216 | { 217 | e.Completed -= new EventHandler(this.SendCompleted); 218 | e.Dispose(); 219 | return; 220 | } 221 | 222 | this._stack.Push(e); 223 | } 224 | #endregion 225 | 226 | #region Private Methods 227 | /// 228 | /// send completed handle 229 | /// 230 | /// 231 | /// 232 | private void SendCompleted(object sender, SocketAsyncEventArgs e) 233 | { 234 | this.ReleaseSocketAsyncEventArgs(e); 235 | } 236 | #endregion 237 | 238 | #region Public Methods 239 | /// 240 | /// sned async 241 | /// 242 | /// 243 | /// 244 | /// endPoint is null 245 | /// payload is null or empty 246 | /// payload length大于messageBufferSize 247 | public void SendAsync(EndPoint endPoint, byte[] payload) 248 | { 249 | if (endPoint == null) throw new ArgumentNullException("endPoint"); 250 | if (payload == null || payload.Length == 0) throw new ArgumentNullException("payload"); 251 | if (payload.Length > this._messageBufferSize) throw new ArgumentOutOfRangeException("payload.Length", "payload length大于messageBufferSize"); 252 | 253 | var e = this.GetSocketAsyncEventArgs(); 254 | e.RemoteEndPoint = endPoint; 255 | 256 | Buffer.BlockCopy(payload, 0, e.Buffer, 0, payload.Length); 257 | e.SetBuffer(0, payload.Length); 258 | 259 | if (!this._socket.SendToAsync(e)) this.ReleaseSocketAsyncEventArgs(e); 260 | } 261 | #endregion 262 | } 263 | } 264 | } -------------------------------------------------------------------------------- /FastNetwork/UdpSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace FastNetwork 5 | { 6 | /// 7 | /// upd session 8 | /// 9 | public sealed class UdpSession 10 | { 11 | #region Members 12 | private readonly IUdpServer _server = null; 13 | /// 14 | /// get remote endPoint 15 | /// 16 | public readonly EndPoint RemoteEndPoint = null; 17 | #endregion 18 | 19 | #region Constructors 20 | /// 21 | /// new 22 | /// 23 | /// 24 | /// 25 | /// server is null 26 | public UdpSession(EndPoint remoteEndPoint, IUdpServer server) 27 | { 28 | if (server == null) throw new ArgumentNullException("server"); 29 | this.RemoteEndPoint = remoteEndPoint; 30 | this._server = server; 31 | } 32 | #endregion 33 | 34 | #region Public Methods 35 | /// 36 | /// sned async 37 | /// 38 | /// 39 | /// payload is null or empty 40 | public void SendAsync(byte[] payload) 41 | { 42 | this._server.SendTo(this.RemoteEndPoint, payload); 43 | } 44 | #endregion 45 | } 46 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/ConsistentHashContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace FastNetwork.Utils 7 | { 8 | /// 9 | /// 一致性哈希container 10 | /// 11 | /// 12 | public sealed class ConsistentHashContainer 13 | { 14 | #region Private Members 15 | private readonly Dictionary _dic = new Dictionary(); 16 | private readonly T[] _arr = null; 17 | private readonly uint[] _keys = null; 18 | #endregion 19 | 20 | #region Constructors 21 | /// 22 | /// new 23 | /// 24 | /// 25 | /// source is null 26 | public ConsistentHashContainer(IDictionary source) 27 | { 28 | if (source == null) throw new ArgumentNullException("source"); 29 | 30 | var servers = new List(); 31 | var keys = new List(); 32 | 33 | foreach (var child in source) 34 | { 35 | for (int i = 0; i < 250; i++) 36 | { 37 | uint key = BitConverter.ToUInt32(new ModifiedFNV1_32().ComputeHash(Encoding.ASCII.GetBytes(child.Key + "-" + i)), 0); 38 | if (!this._dic.ContainsKey(key)) 39 | { 40 | this._dic[key] = child.Value; 41 | keys.Add(key); 42 | } 43 | } 44 | servers.Add(child.Value); 45 | } 46 | 47 | this._arr = servers.ToArray(); 48 | keys.Sort(); 49 | this._keys = keys.ToArray(); 50 | } 51 | #endregion 52 | 53 | #region Private Methods 54 | /// 55 | /// Given an item key hash, 56 | /// this method returns the Server which is closest on the server key continuum. 57 | /// 58 | /// 59 | /// 60 | private T Get(uint consistentKey) 61 | { 62 | int i = Array.BinarySearch(this._keys, consistentKey); 63 | 64 | //If not exact match... 65 | if (i < 0) 66 | { 67 | //Get the index of the first item bigger than the one searched for. 68 | i = ~i; 69 | //If i is bigger than the last index, it was bigger than the last item = use the first item. 70 | if (i >= this._keys.Length) i = 0; 71 | } 72 | return this._dic[this._keys[i]]; 73 | } 74 | #endregion 75 | 76 | #region Public Methods 77 | /// 78 | /// get 79 | /// 80 | /// 81 | /// 82 | public T Get(byte[] consistentKey) 83 | { 84 | if (this._arr.Length == 0) return default(T); 85 | //Quick return if we only have one. 86 | if (this._arr.Length == 1) return this._arr[0]; 87 | return Get(BitConverter.ToUInt32(new ModifiedFNV1_32().ComputeHash(consistentKey), 0)); 88 | } 89 | #endregion 90 | 91 | #region FNV1_32 92 | /// 93 | /// Fowler-Noll-Vo hash, variant 1, 32-bit version. 94 | /// http://www.isthe.com/chongo/tech/comp/fnv/ 95 | /// 96 | public class FNV1_32 : HashAlgorithm 97 | { 98 | private static readonly uint FNV_prime = 16777619; 99 | private static readonly uint offset_basis = 2166136261; 100 | /// 101 | /// hash 102 | /// 103 | protected uint hash; 104 | 105 | /// 106 | /// new 107 | /// 108 | public FNV1_32() 109 | { 110 | HashSizeValue = 32; 111 | } 112 | /// 113 | /// init 114 | /// 115 | public override void Initialize() 116 | { 117 | hash = offset_basis; 118 | } 119 | /// 120 | /// hashcore 121 | /// 122 | /// 123 | /// 124 | /// 125 | protected override void HashCore(byte[] array, int ibStart, int cbSize) 126 | { 127 | int length = ibStart + cbSize; 128 | for (int i = ibStart; i < length; i++) hash = (hash * FNV_prime) ^ array[i]; 129 | } 130 | /// 131 | /// hash final 132 | /// 133 | /// 134 | protected override byte[] HashFinal() 135 | { 136 | return BitConverter.GetBytes(hash); 137 | } 138 | } 139 | #endregion 140 | 141 | #region ModifiedFNV1_32 142 | /// 143 | /// Modified Fowler-Noll-Vo hash, 32-bit version. 144 | /// http://home.comcast.net/~bretm/hash/6.html 145 | /// 146 | public class ModifiedFNV1_32 : FNV1_32 147 | { 148 | /// 149 | /// hashFinal. 150 | /// 151 | /// 152 | protected override byte[] HashFinal() 153 | { 154 | hash += hash << 13; 155 | hash ^= hash >> 7; 156 | hash += hash << 3; 157 | hash ^= hash >> 17; 158 | hash += hash << 5; 159 | return BitConverter.GetBytes(hash); 160 | } 161 | } 162 | #endregion 163 | } 164 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/Date.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Utils 4 | { 5 | /// 6 | /// 关于时间的一些操作 7 | /// 8 | static public class Date 9 | { 10 | #region Private Members 11 | /// 12 | /// unix下的纪元时间 13 | /// 14 | static private readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 15 | /// 16 | /// the max milliseconds since epoch. 17 | /// 18 | static private readonly long dateTimeMaxValueMillisecondsSinceEpoch = (DateTime.MaxValue - unixEpoch).Ticks / 10000; 19 | #endregion 20 | 21 | #region Public Methods 22 | /// 23 | /// Converts a DateTime to UTC (with special handling for MinValue and MaxValue). 24 | /// 25 | /// A DateTime. 26 | /// The DateTime in UTC. 27 | public static DateTime ToUniversalTime(DateTime dateTime) 28 | { 29 | if (dateTime.Kind == DateTimeKind.Utc) return dateTime; 30 | else 31 | { 32 | if (dateTime == DateTime.MinValue) return DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc); 33 | else if (dateTime == DateTime.MaxValue) return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc); 34 | else return dateTime.ToUniversalTime(); 35 | } 36 | } 37 | /// 38 | /// Converts a DateTime to number of milliseconds since Unix epoch. 39 | /// 40 | /// A DateTime. 41 | /// Number of seconds since Unix epoch. 42 | public static long ToMillisecondsSinceEpoch(DateTime dateTime) 43 | { 44 | return (ToUniversalTime(dateTime) - unixEpoch).Ticks / 10000; 45 | } 46 | /// 47 | /// Converts a DateTime to number of seconds since Unix epoch. 48 | /// 49 | /// A DateTime. 50 | /// Number of seconds since Unix epoch. 51 | public static long ToSecondsSinceEpoch(DateTime dateTime) 52 | { 53 | return ToMillisecondsSinceEpoch(dateTime) / 1000; 54 | } 55 | /// 56 | /// Converts from number of milliseconds since Unix epoch to DateTime. 57 | /// 58 | /// The number of milliseconds since Unix epoch. 59 | /// A DateTime. 60 | public static DateTime ToDateTimeFromMillisecondsSinceEpoch(long millisecondsSinceEpoch) 61 | { 62 | // MaxValue has to be handled specially to avoid rounding errors 63 | if (millisecondsSinceEpoch == dateTimeMaxValueMillisecondsSinceEpoch) 64 | return DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc); 65 | else return unixEpoch.AddTicks(millisecondsSinceEpoch * 10000); 66 | } 67 | /// 68 | /// Converts from number of seconds since Unix epoch to DateTime. 69 | /// 70 | /// The number of seconds since Unix epoch. 71 | /// A DateTime. 72 | public static DateTime ToDateTimeFromSecondsSinceEpoch(long secondsSinceEpoch) 73 | { 74 | return ToDateTimeFromMillisecondsSinceEpoch(secondsSinceEpoch * 1000); 75 | } 76 | /// 77 | /// Converts a DateTime to local time (with special handling for MinValue and MaxValue). 78 | /// 79 | /// A DateTime. 80 | /// A DateTimeKind. 81 | /// The DateTime in local time. 82 | public static DateTime ToLocalTime(DateTime dateTime, DateTimeKind kind) 83 | { 84 | if (dateTime.Kind == kind) return dateTime; 85 | else 86 | { 87 | if (dateTime == DateTime.MinValue) return DateTime.SpecifyKind(DateTime.MinValue, kind); 88 | else if (dateTime == DateTime.MaxValue) return DateTime.SpecifyKind(DateTime.MaxValue, kind); 89 | else return DateTime.SpecifyKind(dateTime.ToLocalTime(), kind); 90 | } 91 | } 92 | /// 93 | /// SpecifyKind 94 | /// 95 | /// 96 | /// 97 | /// 98 | public static DateTime SpecifyKind(DateTime dt, DateTimeKind kind) 99 | { 100 | if (dt.Kind == kind) return dt; 101 | return DateTime.SpecifyKind(dt, kind); 102 | } 103 | #endregion 104 | } 105 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/DisposableBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FastNetwork.Utils 4 | { 5 | /// 6 | /// disposable base 7 | /// 8 | public abstract class DisposableBase : IDisposable 9 | { 10 | private bool _disposed = false; 11 | 12 | /// 13 | /// finalize 14 | /// 15 | ~DisposableBase() 16 | { 17 | this.Dispose(false); 18 | } 19 | 20 | /// 21 | /// dispose 22 | /// 23 | public void Dispose() 24 | { 25 | this.Dispose(true); 26 | GC.SuppressFinalize(this); 27 | } 28 | 29 | /// 30 | /// Dispose 31 | /// 32 | /// true表示清理托管资源 33 | private void Dispose(bool disposing) 34 | { 35 | if (this._disposed) return; 36 | this.Free(disposing); 37 | this._disposed = true; 38 | } 39 | 40 | /// 41 | /// free 42 | /// 43 | /// 44 | protected abstract void Free(bool disposing); 45 | 46 | /// 47 | /// 检测并抛出 48 | /// 49 | protected void CheckDisposedWithException() 50 | { 51 | if (this._disposed) throw new ObjectDisposedException(this.GetType().ToString()); 52 | } 53 | /// 54 | /// true表示已disposed 55 | /// 56 | public bool IsDisposed 57 | { 58 | get { return this._disposed; } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/IPUtility.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net; 3 | 4 | namespace FastNetwork.Utils 5 | { 6 | /// 7 | /// ip utility 8 | /// 9 | static public class IPUtility 10 | { 11 | #region Private Members 12 | /// 13 | /// A类: 10.0.0.0-10.255.255.255 14 | /// 15 | static private long ipABegin, ipAEnd; 16 | /// 17 | /// B类: 172.16.0.0-172.31.255.255 18 | /// 19 | static private long ipBBegin, ipBEnd; 20 | /// 21 | /// C类: 192.168.0.0-192.168.255.255 22 | /// 23 | static private long ipCBegin, ipCEnd; 24 | #endregion 25 | 26 | #region Constructors 27 | /// 28 | /// static new 29 | /// 30 | static IPUtility() 31 | { 32 | ipABegin = ConvertToNumber("10.0.0.0"); 33 | ipAEnd = ConvertToNumber("10.255.255.255"); 34 | 35 | ipBBegin = ConvertToNumber("172.16.0.0"); 36 | ipBEnd = ConvertToNumber("172.31.255.255"); 37 | 38 | ipCBegin = ConvertToNumber("192.168.0.0"); 39 | ipCEnd = ConvertToNumber("192.168.255.255"); 40 | } 41 | #endregion 42 | 43 | #region Public Methods 44 | /// 45 | /// ipaddress convert to long 46 | /// 47 | /// 48 | /// 49 | static public long ConvertToNumber(string ipAddress) 50 | { 51 | return ConvertToNumber(IPAddress.Parse(ipAddress)); 52 | } 53 | /// 54 | /// ipaddress convert to long 55 | /// 56 | /// 57 | /// 58 | static public long ConvertToNumber(IPAddress ipAddress) 59 | { 60 | var bytes = ipAddress.GetAddressBytes(); 61 | return bytes[0] * 256 * 256 * 256 + bytes[1] * 256 * 256 + bytes[2] * 256 + bytes[3]; 62 | } 63 | /// 64 | /// true表示为内网IP 65 | /// 66 | /// 67 | /// 68 | static public bool IsIntranet(string ipAddress) 69 | { 70 | return IsIntranet(ConvertToNumber(ipAddress)); 71 | } 72 | /// 73 | /// true表示为内网IP 74 | /// 75 | /// 76 | /// 77 | static public bool IsIntranet(IPAddress ipAddress) 78 | { 79 | return IsIntranet(ConvertToNumber(ipAddress)); 80 | } 81 | /// 82 | /// true表示为内网IP 83 | /// 84 | /// 85 | /// 86 | static public bool IsIntranet(long longIP) 87 | { 88 | return ((longIP >= ipABegin) && (longIP <= ipAEnd) || 89 | (longIP >= ipBBegin) && (longIP <= ipBEnd) || 90 | (longIP >= ipCBegin) && (longIP <= ipCEnd)); 91 | } 92 | /// 93 | /// 获取本机内网IP 94 | /// 95 | /// 96 | static public IPAddress GetLocalIntranetIP() 97 | { 98 | var list = Dns.GetHostEntry(Dns.GetHostName()).AddressList; 99 | foreach (var child in list) 100 | { 101 | if (IsIntranet(child)) return child; 102 | } 103 | 104 | return null; 105 | } 106 | /// 107 | /// 获取本机内网IP列表 108 | /// 109 | /// 110 | static public List GetLocalIntranetIPList() 111 | { 112 | var list = Dns.GetHostEntry(Dns.GetHostName()).AddressList; 113 | var result = new List(); 114 | foreach (var child in list) 115 | { 116 | if (IsIntranet(child)) result.Add(child); 117 | } 118 | 119 | return result; 120 | } 121 | #endregion 122 | } 123 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/NetworkBitConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace FastNetwork.Utils 5 | { 6 | /// 7 | /// network bit converter. 8 | /// 9 | static public class NetworkBitConverter 10 | { 11 | /// 12 | /// 以网络字节数组的形式返回指定的 16 位有符号整数值。 13 | /// 14 | /// 15 | /// 16 | static public byte[] GetBytes(short value) 17 | { 18 | return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)); 19 | } 20 | /// 21 | /// 以网络字节数组的形式返回指定的 32 位有符号整数值。 22 | /// 23 | /// 24 | /// 25 | static public byte[] GetBytes(int value) 26 | { 27 | return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)); 28 | } 29 | /// 30 | /// 以网络字节数组的形式返回指定的 64 位有符号整数值。 31 | /// 32 | /// 33 | /// 34 | static public byte[] GetBytes(long value) 35 | { 36 | return BitConverter.GetBytes(IPAddress.HostToNetworkOrder(value)); 37 | } 38 | 39 | /// 40 | /// 返回由网络字节数组中指定位置的两个字节转换来的 16 位有符号整数。 41 | /// 42 | /// 43 | /// 44 | /// 45 | static public short ToInt16(byte[] value, int startIndex) 46 | { 47 | return IPAddress.NetworkToHostOrder(BitConverter.ToInt16(value, startIndex)); 48 | } 49 | /// 50 | /// 返回由网络字节数组中指定位置的四个字节转换来的 32 位有符号整数。 51 | /// 52 | /// 53 | /// 54 | /// 55 | static public int ToInt32(byte[] value, int startIndex) 56 | { 57 | return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(value, startIndex)); 58 | } 59 | /// 60 | /// 返回由网络字节数组中指定位置的八个字节转换来的 64 位有符号整数。 61 | /// 62 | /// 63 | /// 64 | /// 65 | static public long ToInt64(byte[] value, int startIndex) 66 | { 67 | return IPAddress.NetworkToHostOrder(BitConverter.ToInt64(value, startIndex)); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/ReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace FastNetwork.Utils 6 | { 7 | /// 8 | /// 反射帮助类。 9 | /// 10 | public static class ReflectionHelper 11 | { 12 | /// 13 | /// 获取实现了指定类口类型的基类实例。 14 | /// 15 | /// 接口类型 16 | /// 指定的程序集 17 | /// 18 | /// assembly is null 19 | static public T[] GetImplementObjects(Assembly assembly) 20 | { 21 | if (assembly == null) throw new ArgumentNullException("assembly"); 22 | 23 | return assembly.GetExportedTypes().Where(c => 24 | { 25 | if (c.IsClass && !c.IsAbstract) 26 | { 27 | var interfaces = c.GetInterfaces(); 28 | if (interfaces != null) return interfaces.Contains(typeof(T)); 29 | } 30 | return false; 31 | }).Select(c => (T)c.GetConstructor(new Type[0]).Invoke(new object[0])).ToArray(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /FastNetwork/Utils/TaskEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace FastNetwork.Utils 5 | { 6 | /// 7 | /// task ex 8 | /// 9 | static public class TaskEx 10 | { 11 | /// 12 | /// 延迟执行某个动作 13 | /// 14 | /// 15 | /// 16 | /// dueTime 17 | /// callback is null 18 | public static void Delay(int dueTime, Action callback) 19 | { 20 | if (dueTime < -1) throw new ArgumentOutOfRangeException("dueTime"); 21 | if (callback == null) throw new ArgumentNullException("callback"); 22 | 23 | if (dueTime == 0) 24 | { 25 | try { callback(); } 26 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 27 | return; 28 | } 29 | 30 | Timer timer = null; 31 | timer = new Timer(_ => 32 | { 33 | timer.Dispose(); 34 | try { callback(); } 35 | catch (Exception ex) { Log.Trace.Error(ex.Message, ex); } 36 | }, null, dueTime, Timeout.Infinite); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /FastNetwork/bin/Debug/FastNetwork.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/FastNetwork/bin/Debug/FastNetwork.dll -------------------------------------------------------------------------------- /FastNetwork/bin/Debug/FastNetwork.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/FastNetwork/bin/Debug/FastNetwork.pdb -------------------------------------------------------------------------------- /FastNetwork/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/FastNetwork/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /FastNetwork/obj/Debug/FastNetwork.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | c:\users\sei.zz\documents\visual studio 2012\Projects\FastNetwork\FastNetwork\bin\Debug\FastNetwork.dll 2 | c:\users\sei.zz\documents\visual studio 2012\Projects\FastNetwork\FastNetwork\bin\Debug\FastNetwork.pdb 3 | c:\users\sei.zz\documents\visual studio 2012\Projects\FastNetwork\FastNetwork\obj\Debug\FastNetwork.dll 4 | c:\users\sei.zz\documents\visual studio 2012\Projects\FastNetwork\FastNetwork\obj\Debug\FastNetwork.pdb 5 | -------------------------------------------------------------------------------- /FastNetwork/obj/Debug/FastNetwork.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/FastNetwork/obj/Debug/FastNetwork.dll -------------------------------------------------------------------------------- /FastNetwork/obj/Debug/FastNetwork.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/FastNetwork/obj/Debug/FastNetwork.pdb -------------------------------------------------------------------------------- /PluginEngine/DefaultPlugin.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using PluginEngine; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace PluginEngine 9 | { 10 | [Plugin("祝君", "E-mail:10588690@qq.com", "测试组件", "(C)copyright 2015 祝君", "测试插件系统。")] 11 | public class DefaultPlugin:IPlugin 12 | { 13 | public void Initialize() 14 | { 15 | Console.WriteLine("DefaultPlugin Initialize"); 16 | } 17 | 18 | public void Startup() 19 | { 20 | Console.WriteLine("DefaultPlugin Startup"); 21 | } 22 | 23 | public void ShutDown() 24 | { 25 | Console.WriteLine("DefaultPlugin ShutDown"); 26 | } 27 | 28 | public bool SupportUnload 29 | { 30 | get { return true; } 31 | } 32 | 33 | public bool SupportLoad 34 | { 35 | get { return true; } 36 | } 37 | 38 | public bool CheckCanLoad(bool isFirstCall) 39 | { 40 | return true; 41 | } 42 | 43 | public string Version 44 | { 45 | get 46 | { 47 | return System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /PluginEngine/IPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Drawing; 6 | using FastNetwork; 7 | 8 | namespace PluginEngine 9 | { 10 | /// 11 | /// 插件接口 12 | /// 13 | public interface IPlugin 14 | { 15 | /// 16 | /// 执行初始化 17 | /// 18 | void Initialize(); 19 | 20 | /// 21 | /// 插件启动 22 | /// 23 | void Startup(); 24 | 25 | /// 26 | /// 插件卸载 27 | /// 28 | void ShutDown(); 29 | 30 | /// 31 | /// 是否支持中途卸载 32 | /// 33 | bool SupportUnload { get; } 34 | 35 | /// 36 | /// 是否支持中途加载 37 | /// 38 | bool SupportLoad { get; } 39 | 40 | /// 41 | /// 检查是否可以加载 42 | /// 43 | /// 是否是飞鸽传书初始化时候的加载 44 | /// 45 | bool CheckCanLoad(bool isFirstCall); 46 | 47 | /// 48 | /// 当前运行的插件版本 49 | /// 50 | string Version { get; } 51 | 52 | #region 事件 53 | /// 54 | /// 请求加载配置事件 55 | /// 56 | //event EventHandler RequireLoadConfig; 57 | 58 | /// 59 | /// 请求保存配置事件 60 | /// 61 | //event EventHandler ReuqireSaveConfig; 62 | #endregion 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /PluginEngine/InnerPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | public enum InnerPlugin:int 9 | { 10 | DefaultPlugin = 0, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PluginEngine/PluginAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | /// 9 | /// 服务提供标记 10 | /// 11 | [AttributeUsage(AttributeTargets.Class)] 12 | [Serializable] 13 | public class PluginAttribute : System.Attribute 14 | { 15 | /// 16 | /// 创建 PluginAttribute class 的新实例 17 | /// 18 | public PluginAttribute(string author, string contact, string name, string copyRight, string description) 19 | { 20 | Description = new PluginDescription(author, contact, name, copyRight, description); 21 | } 22 | 23 | /// 24 | /// 创建 PluginAttribute class 的新实例 25 | /// 26 | public PluginAttribute(string author, string contact, string name, string copyRight, string description, bool defaultEnabled) 27 | { 28 | Description = new PluginDescription(author, contact, name, copyRight, description, defaultEnabled); 29 | } 30 | 31 | /// 32 | /// 描述 33 | /// 34 | public PluginDescription Description { get; set; } 35 | 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /PluginEngine/PluginDescription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | /// 9 | /// 插件信息 10 | /// 11 | [Serializable] 12 | public class PluginDescription 13 | { 14 | /// 15 | /// 创建 PluginDescription class 的新实例 16 | /// 17 | public PluginDescription() 18 | { 19 | } 20 | 21 | /// 22 | /// 创建 PluginAttribute class 的新实例 23 | /// 24 | public PluginDescription(string author, string contact, string name, string copyRight, string description) 25 | { 26 | Author = author; 27 | Contact = contact; 28 | Name = name; 29 | CopyRight = copyRight; 30 | Description = description; 31 | DefaultEnabled = true; 32 | } 33 | 34 | /// 35 | /// 创建 PluginAttribute class 的新实例 36 | /// 37 | public PluginDescription(string author, string contact, string name, string copyRight, string description, bool defaultEnabled) 38 | { 39 | Author = author; 40 | Contact = contact; 41 | Name = name; 42 | CopyRight = copyRight; 43 | Description = description; 44 | DefaultEnabled = defaultEnabled; 45 | } 46 | 47 | /// 48 | /// 作者 49 | /// 50 | public string Author { get; set; } 51 | 52 | /// 53 | /// 联系方式 54 | /// 55 | public string Contact { get; set; } 56 | 57 | /// 58 | /// 服务名称 59 | /// 60 | public string Name { get; set; } 61 | 62 | /// 63 | /// 版权标记 64 | /// 65 | public string CopyRight { get; set; } 66 | 67 | /// 68 | /// 功能描述 69 | /// 70 | public string Description { get; set; } 71 | 72 | /// 73 | /// 是否默认开启 74 | /// 75 | public bool DefaultEnabled { get; set; } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /PluginEngine/PluginEngine.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {DC0FB9B6-C12C-42A6-B5B8-9CC2AB64A7E2} 9 | Library 10 | Properties 11 | PluginEngine 12 | PluginEngine 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {eaef8b76-66b2-4502-88de-19d80f016a6b} 58 | FastNetwork 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /PluginEngine/PluginInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | public class PluginInfo 9 | { 10 | /// 11 | /// 插件所在程序集 12 | /// 13 | public string Assembly { get; set; } 14 | 15 | /// 16 | /// 类别名 17 | /// 18 | public string TypeName { get; set; } 19 | 20 | /// 21 | /// 是否启用 22 | /// 23 | public bool Enabled { get; set; } 24 | 25 | /// 26 | /// 构造器 27 | /// 28 | [System.Xml.Serialization.XmlIgnore] 29 | public System.Reflection.ConstructorInfo ConstructorInfo { get; set; } 30 | 31 | /// 32 | /// 实例对象 33 | /// 34 | [System.Xml.Serialization.XmlIgnore] 35 | public IPlugin PluginProvider { get; set; } 36 | 37 | /// 38 | /// 服务信息 39 | /// 40 | [System.Xml.Serialization.XmlIgnore] 41 | public PluginDescription PluginDescription { get; private set; } 42 | 43 | 44 | /// 45 | /// 服务状态 46 | /// 47 | [System.Xml.Serialization.XmlIgnore] 48 | public PluginState State { get; private set; } 49 | 50 | System.Reflection.ConstructorInfo constInfo = null; 51 | 52 | 53 | /// 54 | /// 构造函数 55 | /// 56 | public PluginInfo() 57 | { 58 | State = PluginState.NotInstalled; 59 | } 60 | 61 | 62 | /// 63 | /// 初始化加载 64 | /// 65 | /// 66 | public bool Load() 67 | { 68 | return Load(false); 69 | } 70 | 71 | /// 72 | /// 初始化加载 73 | /// 74 | /// 是否是初始化加载 75 | /// 76 | internal bool Load(bool isInitializingCall) 77 | { 78 | if (EnsureLoadAssembly() && CreateProviderInstance() && InitialzingPluginProvider()) 79 | { 80 | LoadService(isInitializingCall); 81 | 82 | return true; 83 | } 84 | 85 | return false; 86 | } 87 | 88 | /// 89 | /// 加载程序集信息 90 | /// 91 | /// 92 | private bool EnsureLoadAssembly() 93 | { 94 | if (constInfo != null) return true; 95 | 96 | System.Type tp = null; 97 | State = PluginState.NotInstalled; 98 | 99 | if (string.IsNullOrEmpty(Assembly)) 100 | { 101 | try 102 | { 103 | tp = System.Type.GetType(TypeName); 104 | } 105 | catch (Exception) { return false; } 106 | } 107 | else 108 | { 109 | string file = LocateAssemblyPath(Assembly); 110 | if (file == null) return false; 111 | try 112 | { 113 | tp = System.Reflection.Assembly.LoadFile(file).GetType(TypeName); 114 | } 115 | catch (Exception) { return false; } 116 | } 117 | 118 | State = PluginState.LoadingError; 119 | if (tp == null) return false; 120 | 121 | //获得插件的信息 122 | object[] infos = tp.GetCustomAttributes(typeof(PluginAttribute), true); 123 | if (infos != null && infos.Length > 0) 124 | { 125 | this.PluginDescription = (infos[0] as PluginAttribute).Description; 126 | } 127 | else 128 | { 129 | this.PluginDescription = new PluginDescription("未知", "未知", tp.Name, "未知", tp.FullName); 130 | } 131 | 132 | if ((constInfo = tp.GetConstructor(System.Type.EmptyTypes)) == null) return false; 133 | 134 | State = PluginState.TypeLoaded; 135 | return true; 136 | } 137 | 138 | /// 139 | /// 创建实例对象 140 | /// 141 | /// 142 | private bool CreateProviderInstance() 143 | { 144 | if (PluginProvider != null) return true; 145 | 146 | if (State != PluginState.TypeLoaded) return false; 147 | else if (!Enabled) return false; 148 | else 149 | { 150 | try 151 | { 152 | PluginProvider = constInfo.Invoke(new object[] { }) as IPlugin; 153 | State = PluginState.UnInitialized; 154 | } 155 | catch (Exception) 156 | { 157 | State = PluginState.LoadingError; 158 | return false; 159 | } 160 | 161 | return PluginProvider != null; 162 | } 163 | } 164 | 165 | /// 166 | /// 初始化指定插件 167 | /// 168 | /// 169 | private bool InitialzingPluginProvider() 170 | { 171 | if (State != PluginState.UnInitialized) 172 | { 173 | return PluginProvider != null; 174 | } 175 | else 176 | { 177 | PluginProvider.Initialize(); 178 | return true; 179 | } 180 | } 181 | 182 | /// 183 | /// 加载指定插件 184 | /// 185 | private bool LoadService() 186 | { 187 | return LoadService(false); 188 | } 189 | 190 | /// 191 | /// 加载指定插件 192 | /// 193 | /// 是否是飞鸽传书初始化时候的请求 194 | internal bool LoadService(bool onloadCall) 195 | { 196 | if (PluginProvider == null || State == PluginState.Running || !PluginProvider.CheckCanLoad(onloadCall) || (!PluginProvider.SupportLoad && !onloadCall)) 197 | { 198 | return false; 199 | } 200 | else 201 | { 202 | PluginProvider.Startup(); 203 | State = PluginState.Running; 204 | 205 | return true; 206 | } 207 | } 208 | 209 | /// 210 | /// 卸载插件 211 | /// 212 | public bool ShutDown() 213 | { 214 | if (PluginProvider == null || State == PluginState.Unload || !PluginProvider.SupportUnload) 215 | { 216 | return false; 217 | } 218 | else 219 | { 220 | PluginProvider.ShutDown(); 221 | State = PluginState.Unload; 222 | 223 | return true; 224 | } 225 | } 226 | 227 | /// 228 | /// 确定程序集路径 229 | /// 230 | /// 程序集名称 231 | /// 存在的路径.如果找不到,则返回null 232 | string LocateAssemblyPath(string dllName) 233 | { 234 | string RootPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); 235 | //查找同目录 236 | string path = System.IO.Path.Combine(RootPath, dllName); 237 | if (System.IO.File.Exists(path)) return path; 238 | 239 | path = System.IO.Path.Combine(RootPath, "plugin\\" + dllName); 240 | if (System.IO.File.Exists(path)) return path; 241 | 242 | return null; 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /PluginEngine/PluginList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | public class PluginList : List 9 | { 10 | /// 11 | /// 对集合执行操作 12 | /// 13 | /// 要执行的函数 14 | public void ProviderExecute(Action action) 15 | { 16 | this.ForEach(s => 17 | { 18 | if (s.PluginProvider == null) return; 19 | action(s.PluginProvider); 20 | }); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PluginEngine/PluginManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Reflection; 6 | 7 | namespace PluginEngine 8 | { 9 | /// 10 | /// 插件服务管理 11 | /// 12 | public class PluginManager 13 | { 14 | /// 15 | /// 内置的插件类名映射字典 16 | /// 17 | public readonly static Dictionary InnerPluginTypeList; 18 | 19 | 20 | 21 | static PluginManager() 22 | { 23 | InnerPluginTypeList = new Dictionary(); 24 | InnerPluginTypeList.Add(InnerPlugin.DefaultPlugin, typeof(DefaultPlugin).FullName); 25 | } 26 | 27 | /// 28 | /// 通过文件路径来查找所有服务 29 | /// 30 | /// 31 | /// 32 | public static PluginInfo[] GetPluginsInAssembly(string assemblyPath) 33 | { 34 | try 35 | { 36 | return GetPluginsInAssembly(Assembly.LoadFile(assemblyPath)); 37 | } 38 | catch (Exception) 39 | { 40 | return null; 41 | } 42 | } 43 | 44 | /// 45 | /// 查找指定程序集中所有的服务类 46 | /// 47 | /// 48 | /// 49 | public static PluginInfo[] GetPluginsInAssembly(Assembly assembly) 50 | { 51 | System.Type[] types = assembly.GetTypes(); 52 | 53 | List typeList = new List(); 54 | Array.ForEach(types, s => 55 | { 56 | if (!s.IsPublic || s.IsAbstract) return; 57 | Type t = s.GetInterface(typeof(IPlugin).FullName); 58 | if (t == null) return; 59 | 60 | object[] infos = s.GetCustomAttributes(typeof(PluginAttribute), true); 61 | 62 | PluginInfo info = new PluginInfo(); 63 | info.Assembly = System.IO.Path.GetFileName(assembly.Location); 64 | info.TypeName = s.FullName; 65 | 66 | if (infos == null || infos.Length == 0) 67 | { 68 | info.Enabled = true; 69 | } 70 | else 71 | { 72 | info.Enabled = (infos[0] as PluginAttribute).Description.DefaultEnabled; 73 | } 74 | typeList.Add(info); 75 | }); 76 | 77 | return typeList.ToArray(); 78 | } 79 | 80 | /// 81 | /// 获得内置的插件 82 | /// 83 | /// 84 | public static PluginInfo[] GetPluginsInAssembly() 85 | { 86 | return GetPluginsInAssembly(System.Reflection.Assembly.GetExecutingAssembly()); 87 | } 88 | 89 | /// 90 | /// 在指定的路径中查找服务提供者 91 | /// 92 | /// 文件夹列表 93 | /// 查找的结果 94 | public static PluginList GetPlugins(params string[] loaderPath) 95 | { 96 | PluginList list = new PluginList(); 97 | Action loader = s => 98 | { 99 | PluginInfo[] slist = GetPluginsInAssembly(s); 100 | if (slist != null) list.AddRange(slist); 101 | }; 102 | Action folderLoader = s => 103 | { 104 | if (!System.IO.Path.IsPathRooted(s)) 105 | s = System.IO.Path.Combine( 106 | System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location), s); 107 | 108 | string[] files = System.IO.Directory.GetFiles(s, "*.exe"); 109 | Array.ForEach(files, loader); 110 | 111 | files = System.IO.Directory.GetFiles(s, "*.dll"); 112 | Array.ForEach(files, loader); 113 | }; 114 | 115 | folderLoader(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)); 116 | Array.ForEach(loaderPath, folderLoader); 117 | 118 | return list; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /PluginEngine/PluginState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PluginEngine 7 | { 8 | /// 9 | /// 服务运行状态 10 | /// 11 | public enum PluginState : int 12 | { 13 | /// 14 | /// 未安装 15 | /// 16 | NotInstalled = 0, 17 | /// 18 | /// 正在运行 19 | /// 20 | Running = 1, 21 | /// 22 | /// 已禁用 23 | /// 24 | Disabled = 2, 25 | /// 26 | /// 加载错误 27 | /// 28 | LoadingError = 3, 29 | /// 30 | /// 未初始化 31 | /// 32 | UnInitialized = 5, 33 | /// 34 | /// 已卸载 35 | /// 36 | Unload = 4, 37 | /// 38 | /// 类型已加载,但是未初始化 39 | /// 40 | TypeLoaded = 6 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /PluginEngine/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("PluginEngine")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PluginEngine")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("d359700b-2ef7-42c3-90a0-9c8a20906a53")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 内部版本号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /PluginEngine/bin/Debug/FastNetwork.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/bin/Debug/FastNetwork.dll -------------------------------------------------------------------------------- /PluginEngine/bin/Debug/FastNetwork.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/bin/Debug/FastNetwork.pdb -------------------------------------------------------------------------------- /PluginEngine/bin/Debug/PluginEngine.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/bin/Debug/PluginEngine.dll -------------------------------------------------------------------------------- /PluginEngine/bin/Debug/PluginEngine.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/bin/Debug/PluginEngine.pdb -------------------------------------------------------------------------------- /PluginEngine/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /PluginEngine/obj/Debug/PluginEngine.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | c:\users\sei.zz\documents\visual studio 2010\Projects\PluginSystem\PluginEngine\bin\Debug\PluginEngine.dll 2 | c:\users\sei.zz\documents\visual studio 2010\Projects\PluginSystem\PluginEngine\bin\Debug\PluginEngine.pdb 3 | c:\users\sei.zz\documents\visual studio 2010\Projects\PluginSystem\PluginEngine\obj\Debug\PluginEngine.dll 4 | c:\users\sei.zz\documents\visual studio 2010\Projects\PluginSystem\PluginEngine\obj\Debug\PluginEngine.pdb 5 | C:\Users\sei.zz\documents\visual studio 2010\Projects\PluginSystem\PluginEngine\obj\Debug\PluginEngine.csprojResolveAssemblyReference.cache 6 | E:\桌面备份\Documents\Visual Studio 2010\Projects\PluginSystem\PluginEngine\bin\Debug\PluginEngine.dll 7 | E:\桌面备份\Documents\Visual Studio 2010\Projects\PluginSystem\PluginEngine\bin\Debug\PluginEngine.pdb 8 | E:\桌面备份\Documents\Visual Studio 2010\Projects\PluginSystem\PluginEngine\obj\Debug\PluginEngine.dll 9 | E:\桌面备份\Documents\Visual Studio 2010\Projects\PluginSystem\PluginEngine\obj\Debug\PluginEngine.pdb 10 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\bin\Debug\PluginEngine.dll 11 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\bin\Debug\PluginEngine.pdb 12 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\obj\Debug\PluginEngine.dll 13 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\obj\Debug\PluginEngine.pdb 14 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\obj\Debug\PluginEngine.csprojResolveAssemblyReference.cache 15 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\bin\Debug\FastNetwork.dll 16 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\PluginEngine\bin\Debug\FastNetwork.pdb 17 | -------------------------------------------------------------------------------- /PluginEngine/obj/Debug/PluginEngine.csprojResolveAssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/obj/Debug/PluginEngine.csprojResolveAssemblyReference.cache -------------------------------------------------------------------------------- /PluginEngine/obj/Debug/PluginEngine.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/obj/Debug/PluginEngine.dll -------------------------------------------------------------------------------- /PluginEngine/obj/Debug/PluginEngine.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/PluginEngine/obj/Debug/PluginEngine.pdb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastNetwork 2 | 基于SocketAsyncEventArgs的一个高性能异步TCP网络库 3 | ## 作者介绍 4 | 作者是一名软件工程学生党。目前在上海某985高校就读研究生,热爱新技术,热爱编程,为人幽默,热爱开源,研究方向有分布式数据库、高性能网络编程、java中间件 邮箱:zhujunxxxxx@163.com 博客: http://blog.csdn.net/zhujunxxxxx 5 | -------------------------------------------------------------------------------- /Test/DefaultDecoder.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Protocol; 3 | using FastNetwork.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace Test 10 | { 11 | public class DefaultDecoder : IDecoder 12 | { 13 | 14 | object IDecoder.decode(IConnection connection, byte[] buffer) 15 | { 16 | try 17 | { 18 | int namelen = NetworkBitConverter.ToInt32(buffer, 0); 19 | 20 | string name = Encoding.Default.GetString(buffer, 4, namelen); 21 | 22 | int age = NetworkBitConverter.ToInt32(buffer, 4 + namelen); 23 | 24 | return new UserInfo(name, age); 25 | } 26 | catch (Exception) 27 | { 28 | return new UserInfo("error", 0); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Test/DefaultEncoder.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Protocol; 3 | using FastNetwork.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace Test 10 | { 11 | public class DefaultEncoder : IEncoder 12 | { 13 | public byte[] encode(IConnection connection, object obj) 14 | { 15 | UserInfo msg = (UserInfo)obj; 16 | byte[] name = Encoding.Default.GetBytes(msg.username); 17 | 18 | byte[] age = NetworkBitConverter.GetBytes(msg.age); 19 | 20 | byte[] data = new byte[4 + name.Length + 4]; 21 | 22 | Buffer.BlockCopy(NetworkBitConverter.GetBytes(name.Length), 0, data, 0, 4); 23 | 24 | Buffer.BlockCopy(name, 0, data, 4, name.Length); 25 | 26 | Buffer.BlockCopy(age, 0, data, 4 + name.Length, 4); 27 | 28 | return data; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Test/IMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FastNetwork.Protocol 7 | { 8 | /// 9 | /// 接收数据基类 10 | /// 11 | public interface IMessage 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Test/Program.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Protocol; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | 9 | namespace Test 10 | { 11 | 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | FastNetwork.Log.Trace.EnableConsole(); 17 | ServerHandler handler = new ServerHandler(); 18 | DefaultBinaryProtocol protocal = new DefaultBinaryProtocol(); 19 | 20 | SocketServer server = new SocketServer(handler, new DefaultEncoder(),new DefaultDecoder()); 21 | 22 | server.AddListener("tcp", new System.Net.IPEndPoint(IPAddress.Any,8008)); 23 | try 24 | { 25 | server.Start(); 26 | } 27 | catch (Exception e) 28 | { 29 | Console.WriteLine(e.StackTrace); 30 | } 31 | 32 | Console.WriteLine("server start"); 33 | Console.ReadLine(); 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("8345b149-4223-4a27-a1bb-5ac3014286ee")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Test/ServerHandler.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Event; 3 | using FastNetwork.Protocol; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading; 9 | 10 | namespace Test 11 | { 12 | /// 13 | /// 实现函数处理 14 | /// 15 | public class ServerHandler : IServerHandler 16 | { 17 | int count = 0; 18 | public void OnConnected(IConnection connection) 19 | { 20 | Console.WriteLine("connected from:" + connection.RemoteEndPoint.ToString()); 21 | 22 | //开始接收数据,没有这个操作将不接受该连接发送的数据 23 | connection.BeginReceive(); 24 | } 25 | 26 | public void OnStartSending(IConnection connection, Packet packet) 27 | { 28 | //throw new NotImplementedException(); 29 | Console.WriteLine("send beging"); 30 | } 31 | 32 | public void OnSendCallback(IConnection connection, SendCallbackEventArgs e) 33 | { 34 | //throw new NotImplementedException(); 35 | Console.WriteLine("send ok"); 36 | } 37 | 38 | public void OnReceived(IConnection connection, Object obj) 39 | { 40 | //throw new NotImplementedException(); 41 | UserInfo info = (UserInfo)obj; 42 | //Console.WriteLine("receive from " + connection.RemoteEndPoint.ToString()+":"+info.username); 43 | Interlocked.Increment(ref this.count); 44 | 45 | if (count % 1000 == 0) 46 | { 47 | Console.WriteLine("receive:" + count); 48 | } 49 | 50 | } 51 | 52 | public void OnDisconnected(IConnection connection, Exception ex) 53 | { 54 | Console.WriteLine("disconnected from:" + connection.RemoteEndPoint.ToString()); 55 | } 56 | 57 | public void OnException(IConnection connection, Exception ex) 58 | { 59 | //throw new NotImplementedException(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Test/Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D91D5EF9-D0B2-41D0-BF9D-17CAD844EEF3} 8 | Exe 9 | Properties 10 | Test 11 | Test 12 | v4.0 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {eaef8b76-66b2-4502-88de-19d80f016a6b} 55 | FastNetwork 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /Test/UserInfo.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Protocol; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Test 8 | { 9 | public class UserInfo:IMessage 10 | { 11 | public string username; 12 | public int age; 13 | public UserInfo(string name, int age) 14 | { 15 | this.username = name; 16 | this.age = age; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Test/bin/Debug/Debug.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/Debug.rar -------------------------------------------------------------------------------- /Test/bin/Debug/FastNetwork.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/FastNetwork.dll -------------------------------------------------------------------------------- /Test/bin/Debug/FastNetwork.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/FastNetwork.pdb -------------------------------------------------------------------------------- /Test/bin/Debug/Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/Test.exe -------------------------------------------------------------------------------- /Test/bin/Debug/Test.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/Test.pdb -------------------------------------------------------------------------------- /Test/bin/Debug/Test.vshost.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/bin/Debug/Test.vshost.exe -------------------------------------------------------------------------------- /Test/bin/Debug/Test.vshost.exe.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Test/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /Test/obj/Debug/Test.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\bin\Debug\Test.exe 2 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\bin\Debug\Test.pdb 3 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\bin\Debug\FastNetwork.dll 4 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\bin\Debug\FastNetwork.pdb 5 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\obj\Debug\Test.csprojResolveAssemblyReference.cache 6 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\obj\Debug\Test.exe 7 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\Test\obj\Debug\Test.pdb 8 | -------------------------------------------------------------------------------- /Test/obj/Debug/Test.csprojResolveAssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/obj/Debug/Test.csprojResolveAssemblyReference.cache -------------------------------------------------------------------------------- /Test/obj/Debug/Test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/obj/Debug/Test.exe -------------------------------------------------------------------------------- /Test/obj/Debug/Test.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/Test/obj/Debug/Test.pdb -------------------------------------------------------------------------------- /TestClient/ClientHandler.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace TestClient 8 | { 9 | public class ClientHandler:IClientHandler 10 | { 11 | public BaseSocketClient _client = null; 12 | 13 | 14 | public void OnConnected(FastNetwork.IConnection connection) 15 | { 16 | Console.WriteLine("connected server"); 17 | 18 | 19 | } 20 | 21 | public void OnStartSending(FastNetwork.IConnection connection, FastNetwork.Packet packet) 22 | { 23 | //Console.WriteLine("start sending"); 24 | } 25 | 26 | public void OnSendCallback(FastNetwork.IConnection connection, FastNetwork.Event.SendCallbackEventArgs e) 27 | { 28 | //Console.WriteLine("send callback"); 29 | 30 | //UserInfo info = new UserInfo("zhujun", 18); 31 | 32 | //_client.Send(info); 33 | } 34 | 35 | public void OnReceived(FastNetwork.IConnection connection, object obj) 36 | { 37 | Console.WriteLine("receive data"); 38 | } 39 | 40 | public void OnDisconnected(FastNetwork.IConnection connection, Exception ex) 41 | { 42 | Console.WriteLine("disconnect with server"); 43 | } 44 | 45 | public void OnException(FastNetwork.IConnection connection, Exception ex) 46 | { 47 | Console.WriteLine("error"); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /TestClient/DefaultDecoder.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Protocol; 3 | using FastNetwork.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace TestClient 10 | { 11 | public class DefaultDecoder : IDecoder 12 | { 13 | 14 | object IDecoder.decode(IConnection connection, byte[] buffer) 15 | { 16 | try 17 | { 18 | int namelen = NetworkBitConverter.ToInt32(buffer, 0); 19 | 20 | string name = Encoding.Default.GetString(buffer, 4, namelen); 21 | 22 | int age = NetworkBitConverter.ToInt32(buffer, 4 + namelen); 23 | 24 | return new UserInfo(name, age); 25 | } 26 | catch (Exception) 27 | { 28 | return new UserInfo("error", 0); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TestClient/DefaultEncoder.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork; 2 | using FastNetwork.Protocol; 3 | using FastNetwork.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace TestClient 10 | { 11 | public class DefaultEncoder : IEncoder 12 | { 13 | public byte[] encode(IConnection connection, object obj) 14 | { 15 | UserInfo msg = (UserInfo)obj; 16 | byte[] name = Encoding.Default.GetBytes(msg.username); 17 | 18 | byte[] age = NetworkBitConverter.GetBytes(msg.age); 19 | 20 | byte[] data = new byte[4 + name.Length + 4]; 21 | 22 | Buffer.BlockCopy(NetworkBitConverter.GetBytes(name.Length), 0, data, 0, 4); 23 | 24 | Buffer.BlockCopy(name, 0, data, 4, name.Length); 25 | 26 | Buffer.BlockCopy(age, 0, data, 4 + name.Length, 4); 27 | 28 | return data; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TestClient/IMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace TestClient 7 | { 8 | /// 9 | /// 接收数据基类 10 | /// 11 | public interface IMessage 12 | { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TestClient/Program.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Client; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using System.Threading; 8 | 9 | namespace TestClient 10 | { 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | FastNetwork.Log.Trace.EnableConsole(); 16 | for (int i = 0; i < 50; i++) 17 | { 18 | Thread td1 = new Thread(run); 19 | td1.Start(); 20 | } 21 | 22 | } 23 | static void run() 24 | { 25 | ClientHandler handler = new ClientHandler(); 26 | 27 | DefaultSocketClient client = new DefaultSocketClient(IPAddress.Parse("127.0.0.1"), 8008, handler, new DefaultEncoder()); 28 | handler._client = client; 29 | client.Start(); 30 | 31 | UserInfo info = null; 32 | string msg = "messagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessagemessage"; 33 | for (int i = 0; ; i++) 34 | { 35 | info = new UserInfo(msg + msg + msg, 18); 36 | client.Send(info); 37 | Thread.Sleep(1); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TestClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过以下 6 | // 特性集控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("TestClient")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestClient")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型, 19 | // 则将该类型上的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("b48255e0-7c46-4ea3-a587-2d7f7ca4fc5c")] 24 | 25 | // 程序集的版本信息由下面四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestClient/TestClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5EBAFC67-DC1A-4DA7-90F8-0B2F1A379700} 8 | Exe 9 | Properties 10 | TestClient 11 | TestClient 12 | v4.0 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {eaef8b76-66b2-4502-88de-19d80f016a6b} 55 | FastNetwork 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /TestClient/UserInfo.cs: -------------------------------------------------------------------------------- 1 | using FastNetwork.Protocol; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace TestClient 8 | { 9 | public class UserInfo:IMessage 10 | { 11 | public string username; 12 | public int age; 13 | public UserInfo(string name, int age) 14 | { 15 | this.username = name; 16 | this.age = age; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TestClient/bin/Debug/FastNetwork.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/bin/Debug/FastNetwork.dll -------------------------------------------------------------------------------- /TestClient/bin/Debug/FastNetwork.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/bin/Debug/FastNetwork.pdb -------------------------------------------------------------------------------- /TestClient/bin/Debug/TestClient.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/bin/Debug/TestClient.exe -------------------------------------------------------------------------------- /TestClient/bin/Debug/TestClient.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/bin/Debug/TestClient.pdb -------------------------------------------------------------------------------- /TestClient/bin/Debug/TestClient.vshost.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/bin/Debug/TestClient.vshost.exe -------------------------------------------------------------------------------- /TestClient/bin/Debug/TestClient.vshost.exe.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestClient/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /TestClient/obj/Debug/TestClient.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\obj\Debug\TestClient.csprojResolveAssemblyReference.cache 2 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\bin\Debug\TestClient.exe 3 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\bin\Debug\TestClient.pdb 4 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\bin\Debug\FastNetwork.dll 5 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\bin\Debug\FastNetwork.pdb 6 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\obj\Debug\TestClient.exe 7 | C:\Users\sei.zz\Documents\Visual Studio 2012\Projects\FastNetwork\TestClient\obj\Debug\TestClient.pdb 8 | -------------------------------------------------------------------------------- /TestClient/obj/Debug/TestClient.csprojResolveAssemblyReference.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/obj/Debug/TestClient.csprojResolveAssemblyReference.cache -------------------------------------------------------------------------------- /TestClient/obj/Debug/TestClient.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/obj/Debug/TestClient.exe -------------------------------------------------------------------------------- /TestClient/obj/Debug/TestClient.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gloriawish/FastNetwork/d2bc63e76c40f63e2e2499c32efc6d827b31e4ba/TestClient/obj/Debug/TestClient.pdb --------------------------------------------------------------------------------