├── 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
--------------------------------------------------------------------------------