C/S模型之Socket通讯 服务侦听端

   本篇文章讲述Socket的通讯,为基于Socket通讯的C/S模型提供基础.

   Socket通讯通常由两部份组成,一个服务侦听端,一个客户连接端,服务端侦听进站的消息,客户端发送出站的消息,二者不可或缺,下面先讲服务端侦听,该类定义为TcpIpListener(一个抽象类):

1.侦听Socket的创建:CreateListenSocket

  该过程比较简单:在该过程中初始化了侦听Socket(g_ListenSocket),使用IP地址族,流类型,Tcp传输控制协义三个参数创建Socket,并且将其关联到侦听端口(对于侦听Socket这个一定要),另外在该过程中还处始化了一个信号量g_MaxSemaphore,该信号量是为了控制同时在线连接数用的.

2.启动侦听器:StartListen

  在该过程中首先对侦听Socket(g_ListenSocket)调用Listen以开始侦听连接请求,之后调用StartAccept方法开始接受异步连接.

  StartAccept方法:该方法首先g_MaxSemaphore.WaitOne(),等待信号,如果已连接数超过信号量则会阻止,否则通过,

之后的一段代码是获取异步接受连接的必需参数SocketAsyncEventArgs(对该类型不熟的请自行参阅MSN),应该比较容易理解,即:如果有传进不为null的参数,则说明有已使用过的SocketAsyncEventArgs,那么就对其进行必要的设置后(重设SocketError,AcceptSocket这两个属性)使用,否则就去缓冲池中取一个,并设置Completed事件处理程序OnAcceptCompleted,这里的缓冲池就是回收使用过的SocketAsyncEventArgs的类,由于SocketAsyncEventArgs类比较大且使用又频繁,所以使用缓冲池,当然你也可以不使用,直接new一个.完成准备工作后就对侦听Socket调用AcceptAsync,该方法是一个使用SocketAsyncEventArgs类的异步接受传入的连接的方法,该方法返回True则说明在等待接受的连接,一旦接受到连接则会引发SocketAsyncEventArgs的Completed事件,如果返回False,则说明连接已同步接受,此时可以直接处理接受的连接,本过程是直接调用OnAcceptCompleted来处理接受的连接,不论返回True或Fasle接受到的连接都存储在SocketAsyncEventArgs的AcceptSocket属性中

3.连接处理例程:OnAcceptCompleted

该例程仅处理SocketAsyncOperation.Accept类型的事件,其实在本例中也只会有该类型的事件,首先,如果是因为关闭侦听Socket而引发的则会收参数后返回,否则启动一个线程(StartingOnAcceptedConnection)处理已连接的Socket,再后使用已有的参数调用StartAccept以便等待下一个连接

4.已连接的处理:StartingOnAcceptedConnection

  该方法简单,只是保存了已连接的Socket并且调用必需重载的方法OnAcceptedConnection通知继承者有连接已接收,右继承者来使用已连接的Socket进行收发数据的操作(并由使用者负责关闭),只是继承者操作完毕后一定要调用基类的OverOneConnection方法来通知已连接的Socket已使用完毕,否则当连接数到达信号量水平时会阻塞新进的连接

5.关闭侦听器:StopListen

该方法关闭侦听Socket并关闭信号量,清空接受连接的Socket列表

以下是该类的完整代码:

TcpIpListener
  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Net.Sockets;
6 using System.Threading;
7 using System.Net;
8
9 namespace YZKStdLibrary.Network.Transe
10 {
11 public abstract class TcpIpListener
12 {
13
14 protected TcpIpListener()
15 {
16 g_ListenSocket = null;
17 g_MaxSemaphore = null;
18 g_Stop = false;
19 g_StartAsyncObject = new object();
20 g_AcceptedSocket = new List<Socket>();
21 }
22
23 #region 私有变量
24
25 private Socket g_ListenSocket;
26
27 private Semaphore g_MaxSemaphore;
28
29 private bool g_Stop;
30
31 private object g_StartAsyncObject;
32
33 private List<Socket> g_AcceptedSocket;
34 #endregion
35
36 #region 私有方法
37
38 private bool CreateListenSocket(IPEndPoint localEndPoint, int maxclientcount)
39 {
40 try
41 {
42 g_Stop = false;
43 g_MaxSemaphore = new Semaphore(maxclientcount, maxclientcount);
44 g_ListenSocket = new Socket(localEndPoint.AddressFamily,
45 SocketType.Stream, ProtocolType.Tcp);
46 g_ListenSocket.Bind(localEndPoint);
47 return true;
48 }
49 catch { return false; }
50 }
51
52 private void CloseSocket(Socket socket)
53 {
54 if (socket != null)
55 {
56 try
57 {
58 if (!g_Stop)
59 socket.Shutdown(SocketShutdown.Both);
60 }
61 catch { }
62 try
63 {
64 socket.Close();
65 }
66 catch { }
67 }
68 }
69
70 private bool StartAccept(SocketAsyncEventArgs arg)
71 {
72 Socket s = g_ListenSocket;
73 if (s != null)
74 {
75 g_MaxSemaphore.WaitOne();
76 SocketAsyncEventArgs x = arg;
77 if (x == null)
78 {
79 x = TcpIpTranseInterface.SocketArgPools.GetItem();
80 x.SocketError = SocketError.Success;
81 x.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
82 }
83 else
84 {
85 x.SocketError = SocketError.Success;
86 x.AcceptSocket = null;
87 }
88 bool isasync = false;
89 try
90 {
91 isasync = s.AcceptAsync(x);
92 }
93 catch (Exception err)
94 {
95 if (!g_Stop)
96 OnUnkownError(err);
97 return false;
98 }
99 if (!isasync)
100 {
101 OnAcceptCompleted(s, x);
102 }
103 return true;
104 }
105 return false;
106 }
107
108 private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
109 {
110 if (e.LastOperation == SocketAsyncOperation.Accept)
111 {
112
113 if (g_Stop)
114 {
115 RecyArg(e);
116 return;
117 }
118 Socket soekct = e.AcceptSocket;
119 e.AcceptSocket = null;
120 if (e.SocketError == SocketError.Success)
121 {
122 System.Threading.Tasks.Task.Factory.StartNew(StartingOnAcceptedConnection, soekct);
123 }
124 int failcount = 0;
125 while (!StartAccept(e))
126 {
127 failcount++;
128 if (g_Stop)
129 break;
130 if (failcount > 10)
131 break;
132 }
133 }
134 }
135
136 private void RecyArg(SocketAsyncEventArgs e)
137 {
138 e.AcceptSocket = null;
139 e.Completed -= new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
140 TcpIpTranseInterface.SocketArgPools.RecyItem(e);
141 }
142
143 private void StartingOnAcceptedConnection(object socket)
144 {
145 Socket s = socket as Socket;
146 AddAcceptedSocket(s);
147 try
148 {
149 OnAcceptedConnection(s);
150 }
151 catch (Exception err)
152 {
153 RemoveAcceptSocket(s);
154 try
155 {
156 OnUnkownError(err);
157 }
158 catch { }
159 }
160 }
161
162 private bool StartListen(int backlog)
163 {
164 g_ListenSocket.Listen(backlog);
165 return StartAccept(null);
166 }
167
168 private void CloseListenSocket()
169 {
170 if (g_ListenSocket != null)
171 {
172 try
173 {
174 g_ListenSocket.Shutdown(SocketShutdown.Both);
175 }
176 catch { }
177 try
178 {
179 g_ListenSocket.Close();
180 }
181 catch { }
182 }
183 }
184
185 private void StopListen()
186 {
187 g_Stop = true;
188 CloseListenSocket();
189 g_ListenSocket = null;
190 if (g_MaxSemaphore != null)
191 {
192 try
193 {
194 g_MaxSemaphore.Close();
195 }
196 catch { }
197 try
198 {
199 g_MaxSemaphore.Dispose();
200 }
201 catch { }
202 g_MaxSemaphore = null;
203 }
204 lock (g_AcceptedSocket)
205 {
206 g_AcceptedSocket.Clear();
207 }
208 }
209
210 private void AddAcceptedSocket(Socket s)
211 {
212 lock (g_AcceptedSocket)
213 {
214 g_AcceptedSocket.Add(s);
215 }
216 }
217
218 private void RemoveAcceptSocket(Socket s)
219 {
220 lock (g_AcceptedSocket)
221 {
222 if (g_AcceptedSocket.Contains(s))
223 {
224 if (g_AcceptedSocket.Remove(s))
225 {
226 try
227 {
228 g_MaxSemaphore.Release();
229 }
230 catch { }
231 }
232 }
233 }
234 }
235 #endregion
236
237 #region 受保护方法
238
239 protected bool Start(
240 int backlog,
241 IPEndPoint localEndPoint,
242 int maxclientcount)
243 {
244 lock (g_StartAsyncObject)
245 {
246 if (g_ListenSocket != null)
247 return true;
248 if (CreateListenSocket(localEndPoint, maxclientcount))
249 {
250 if (StartListen(backlog))
251 return true;
252 else
253 {
254 StopListen();
255 return false;
256 }
257 }
258 return false;
259 }
260 }
261
262 protected void Stop()
263 {
264 lock (g_StartAsyncObject)
265 {
266 StopListen();
267 }
268 }
269
270 protected void OverOneConnection(Socket s)
271 {
272 RemoveAcceptSocket(s);
273 }
274
275 protected EndPoint LocalEndPoint
276 {
277 get
278 {
279 if (g_ListenSocket != null)
280 return g_ListenSocket.LocalEndPoint;
281 return null;
282 }
283 }
284 #endregion
285
286 #region 可重载成员
287
288 protected virtual void OnUnkownError(Exception error)
289 {
290 }
291
292 #endregion
293
294 #region 必需重载成员
295
296 protected abstract void OnAcceptedConnection(Socket socket);
297
298 #endregion
299 }
300 }

 

 

posted on 2011-12-23 13:38  悠竹客  阅读(3130)  评论(3编辑  收藏  举报

导航