C#异步TCP服务器完整实现
TCP异步Socket模型
C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供 BeginConnect、BeginAccept、BeginSend 和 BeginReceive等。IAsyncResult BeginAccept(AsyncCallback callback, object state);
AsyncCallback 回调在函数执⾏完毕后执⾏。state 对象被⽤于在执⾏函数和回调函数间传输信息。
Socket socket = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, 8888);
socket.Bind(iep);
socket.Listen(5);
socket.BeginAccept (new AsyncCallback(CallbackAccept), socket);
private void CallbackAccept(IAsyncResult iar)
{
Socket rver = (Socket)iar.AsyncState;
Socket client = rver.EndAccept(iar);
}
则在Accept⼀个TcpClient,需要维护TcpClient列表。
private List<TcpClientState> clients;
异步TCP服务器完整实现
1///<summary>
2///异步TCP服务器
3///</summary>
4public class AsyncTcpServer : IDisposable
5 {
6#region Fields
7
8private TcpListener listener;
9private List<TcpClientState> clients;
10private bool dispod = fal;
11
12#endregion
13
chinanet14#region Ctors
15
16///<summary>
17///异步TCP服务器
18///</summary>
19///<param name="listenPort">监听的端⼝</param>
20public AsyncTcpServer(int listenPort)
21 : this(IPAddress.Any, listenPort)
22 {
23 }
24
25///<summary>
26///异步TCP服务器
27///</summary>
28///<param name="localEP">监听的终结点</param>
29public AsyncTcpServer(IPEndPoint localEP)
30 : this(localEP.Address, localEP.Port)
31 {
32 }
33
34///<summary>
35///异步TCP服务器
36///</summary>
37///<param name="localIPAddress">监听的IP地址</param>
38///<param name="listenPort">监听的端⼝</param>
39public AsyncTcpServer(IPAddress localIPAddress, int listenPort)
40 {
41 Address = localIPAddress;
42 Port = listenPort;
43this.Encoding = Encoding.Default;
44
45 clients = new List<TcpClientState>();
46
47 listener = new TcpListener(Address, Port);
48 listener.AllowNatTraversal(true);
49 }
50
51#endregion
52
53#region Properties
54
55///<summary>
naomi campbell56///服务器是否正在运⾏
57///</summary>
58public bool IsRunning { get; private t; }
59///<summary>
60///监听的IP地址
61///</summary>
61///</summary>
62public IPAddress Address { get; private t; }
63///<summary>
64///监听的端⼝
65///</summary>
66public int Port { get; private t; }
67///<summary>
68///通信使⽤的编码
69///</summary>
70public Encoding Encoding { get; t; }
71
72#endregion
73
74#region Server
75
76///<summary>
77///启动服务器
78///</summary>
79///<returns>异步TCP服务器</returns>
80public AsyncTcpServer Start()
81 {
82if (!IsRunning)
83 {
84 IsRunning = true;
85 listener.Start();
86 listener.BeginAcceptTcpClient(
87new AsyncCallback(HandleTcpClientAccepted), listener);
88 }
89return this;
90 }
91
92///<summary>
93///启动服务器
94///</summary>
95///<param name="backlog">
96///服务器所允许的挂起连接序列的最⼤长度
97///</param>
98///<returns>异步TCP服务器</returns>
99public AsyncTcpServer Start(int backlog)
100 {
101if (!IsRunning)
102 {
103 IsRunning = true;
104 listener.Start(backlog);
105 listener.BeginAcceptTcpClient(
106new AsyncCallback(HandleTcpClientAccepted), listener); 107 }
108return this;
109 }
110
111///<summary>
112///停⽌服务器
113///</summary>
114///<returns>异步TCP服务器</returns>
115public AsyncTcpServer Stop()
116 {
117if (IsRunning)
118 {
119 IsRunning = fal;
120 listener.Stop();
121
122lock (this.clients)
123 {
124for (int i = 0; i < this.clients.Count; i++)
125 {
126this.clients[i].TcpClient.Client.Disconnect(fal);
127 }
128this.clients.Clear();
129 }
130
131 }
132return this;
133 }
134
135#endregion
136
137#region Receive
138
139private void HandleTcpClientAccepted(IAsyncResult ar) 140 {
141if (IsRunning)
142 {
143 TcpListener tcpListener = (TcpListener)ar.AsyncState; 144
145 TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
145 TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
146byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
147
148 TcpClientState internalClient
149 = new TcpClientState(tcpClient, buffer);
150lock (this.clients)
151 {
152this.clients.Add(internalClient);
153 RaiClientConnected(tcpClient);
154 }
155
156 NetworkStream networkStream = internalClient.NetworkStream;
157 networkStream.BeginRead(
158 internalClient.Buffer,
1590,
160 internalClient.Buffer.Length,
161 HandleDatagramReceived,
162 internalClient);
163
164 tcpListener.BeginAcceptTcpClient(
165new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
166 }
167 }
168
169private void HandleDatagramReceived(IAsyncResult ar)
170 {
171if (IsRunning)
172 {
173 TcpClientState internalClient = (TcpClientState)ar.AsyncState;
174 NetworkStream networkStream = internalClient.NetworkStream;
175
176int numberOfReadBytes = 0;
177try
178 {
179 numberOfReadBytes = networkStream.EndRead(ar);
180 }
181catch
182 {
183 numberOfReadBytes = 0;
184 }
185
186if (numberOfReadBytes == 0)
187 {
188// connection has been clod
189lock (this.clients)
190 {
191this.clients.Remove(internalClient);
192 RaiClientDisconnected(internalClient.TcpClient);
193return;
194 }
195 }
196
197// received byte and trigger event notification
198byte[] receivedBytes = new byte[numberOfReadBytes];
199 Buffer.BlockCopy(
200 internalClient.Buffer, 0,
201 receivedBytes, 0, numberOfReadBytes);
202 RaiDatagramReceived(internalClient.TcpClient, receivedBytes);
203 RaiPlaintextReceived(internalClient.TcpClient, receivedBytes);
204
205// continue listening for tcp datagram packets
206 networkStream.BeginRead(
207 internalClient.Buffer,
2080,
209 internalClient.Buffer.Length,
210 HandleDatagramReceived,
211 internalClient);
212 }
213 }
214
215#endregion
vagueness216
217#region Events
218
219///<summary>
220///接收到数据报⽂事件
221///</summary>
222public event EventHandler<TcpDatagramReceivedEventArgs<byte[]>> DatagramReceived; 223///<summary>
224///接收到数据报⽂明⽂事件
225///</summary>
226public event EventHandler<TcpDatagramReceivedEventArgs<string>> PlaintextReceived; 227
228private void RaiDatagramReceived(TcpClient nder, byte[] datagram)
229 {
230if (DatagramReceived != null)
230if (DatagramReceived != null)
231 {
232 DatagramReceived(this, new TcpDatagramReceivedEventArgs<byte[]>(nder, datagram)); 233 }
234 }
235
236private void RaiPlaintextReceived(TcpClient nder, byte[] datagram)
237 {
238if (PlaintextReceived != null)
239 {
240 PlaintextReceived(this, new TcpDatagramReceivedEventArgs<string>(
241 nder, this.Encoding.GetString(datagram, 0, datagram.Length)));
242 }
243 }
244
245///<summary>
246///与客户端的连接已建⽴事件
247///</summary>
248public event EventHandler<TcpClientConnectedEventArgs> ClientConnected;
249///<summary>
250///与客户端的连接已断开事件
251///</summary>
252public event EventHandler<TcpClientDisconnectedEventArgs> ClientDisconnected;
253
254private void RaiClientConnected(TcpClient tcpClient)
255 {
256if (ClientConnected != null)
257 {
258 ClientConnected(this, new TcpClientConnectedEventArgs(tcpClient));
259 }
260 }
261
262private void RaiClientDisconnected(TcpClient tcpClient)
263 {
264if (ClientDisconnected != null)
265 {
266 ClientDisconnected(this, new TcpClientDisconnectedEventArgs(tcpClient));
267 }
268 }
269
270#endregion
271
272#region Send
273
274///<summary>
275///发送报⽂⾄指定的客户端
276///</summary>
277///<param name="tcpClient">客户端</param>
i do 电影278///<param name="datagram">报⽂</param>
279public void Send(TcpClient tcpClient, byte[] datagram)
280 {
281if (!IsRunning)
282throw new InvalidProgramException("This TCP rver has not been started.");
283
284if (tcpClient == null)
285throw new ArgumentNullException("tcpClient");
286
287if (datagram == null)
288throw new ArgumentNullException("datagram");
289
ecci
290 tcpClient.GetStream().BeginWrite(
291 datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);
292 }
293
294private void HandleDatagramWritten(IAsyncResult ar)
295 {
296 ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
297 }
298
299///<summary>
300///发送报⽂⾄指定的客户端
301///</summary>
302///<param name="tcpClient">客户端</param>
303///<param name="datagram">报⽂</param>
304public void Send(TcpClient tcpClient, string datagram)
305 {
306 Send(tcpClient, this.Encoding.GetBytes(datagram));
307 }
308
309///<summary>
310///发送报⽂⾄所有客户端
311///</summary>
312///<param name="datagram">报⽂</param>
313public void SendAll(byte[] datagram)
314 {
314 {
315if (!IsRunning)
316throw new InvalidProgramException("This TCP rver has not been started."); 317
318for (int i = 0; i < this.clients.Count; i++)
319 {
320 Send(this.clients[i].TcpClient, datagram);
321 }
322 }
323
324///<summary>
325///发送报⽂⾄所有客户端
326///</summary>
327///<param name="datagram">报⽂</param>
328public void SendAll(string datagram)
329 {
330if (!IsRunning)
331throw new InvalidProgramException("This TCP rver has not been started."); 332
333 SendAll(this.Encoding.GetBytes(datagram));
334 }
335
336#endregion
337
338#region IDisposable Members
339
340///<summary>
341/// Performs application-defined tasks associated with freeing,
342/// releasing, or retting unmanaged resources.
343///</summary>
344public void Dispo()
345 {
346 Dispo(true);
347 GC.SuppressFinalize(this);
348 }
349
350///<summary>
351/// Releas unmanaged and - optionally - managed resources
352///</summary>
353///<param name="disposing"><c>true</c> to relea
354/// both managed and unmanaged resources; <c>fal</c>
355/// to relea only unmanaged resources.</param>
356protected virtual void Dispo(bool disposing)
357 {
358if (!this.dispod)
359 {
360if (disposing)
361 {
362try
363 {
364 Stop();
365
366if (listener != null)
367 {
368 listener = null;
369 }
370 }
371catch (SocketException ex)
372 {
373 ExceptionHandler.Handle(ex);
374 }
375 }
烟台家教
376
377 dispod = true;
378 }
379 }
380
381#endregion
382 }
overall是什么意思使⽤举例
1class Program
等一下韩语
2 {
3static AsyncTcpServer rver;
4
5static void Main(string[] args)
6 {
7 LogFactory.Assign(new ConsoleLogFactory());
8
9 rver = new AsyncTcpServer(9999);
10 rver.Encoding = Encoding.UTF8;
11 rver.ClientConnected +=
12new EventHandler<TcpClientConnectedEventArgs>(rver_ClientConnected);
13 rver.ClientDisconnected +=
英语机构加盟
manchester14new EventHandler<TcpClientDisconnectedEventArgs>(rver_ClientDisconnected);
15 rver.PlaintextReceived +=