国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
高性能Socket設(shè)計實現(xiàn) - 志良的技術(shù)博客 - 博客園

因為學(xué)習(xí)的需要,要求一個高性能的Socket服務(wù)器來提供多而繁雜的客戶端連接請求,參考了許多資料和各位的思想,自己琢磨出了一套方案,覺的可行,于是拿出來曬曬,希望大家一起學(xué)習(xí)改進。(這個方案的1.0版本已經(jīng)貼出來了,但是由于本人覺的1.0不太完美,做了下改進,本篇講的主要是2.0)

1.0的文章參考:http://www.cnblogs.com/niuchenglei/archive/2009/07/23/1529462.html
1.0和2.0性能上基本沒有變化,只是針對某些地方做了改進性的修改,本篇主要介紹原理,并貼出部分代碼,上一篇是一個Overview。

設(shè)計原則:使用.net的SocketAsyncEventArgs(原因是這個比較簡單,而且性能也很好,當(dāng)然要是c++的話就用IOCP了)??紤]到能快速的反應(yīng)用戶的連接請求我采用了連接池的技術(shù),類似于sqlserver的連接池,當(dāng)然我的“池”還不夠好,為了能快速的處理接受的數(shù)據(jù)我又加入了一個緩沖區(qū)池,說白了就是給每一個連接對象事先開辟好了空間。在傳輸方面,為了保證數(shù)據(jù)的有效性我們采用客戶端和服務(wù)器端的驗證(當(dāng)然也不是太復(fù)雜)。

具體分析:分析的順序是自底向上的

1.MySocketAsyncEventArgs類:這個類是一個繼承自System.Net.Socket.SocketAsyncEventArgs類,是由于特定情況需要而添加了一些外加屬性的類。

1 internal sealed class MySocketAsyncEventArgs : SocketAsyncEventArgs
2 {
3 internal string UID;
4 private string Property;
5 internal MySocketAsyncEventArgs(string property){
6 this.Property = property;
7 }
8 }

UID:用戶標(biāo)識符,用來標(biāo)識這個連接是那個用戶的。
Property:標(biāo)識該連接是用來發(fā)送信息還是監(jiān)聽接收信息的。param:Receive/Send,MySocketAsyncEventArgs類只帶有一個參數(shù)的構(gòu)造函數(shù),說明類在實例化時就被說明是用來完成接收還是發(fā)送任務(wù)的。

2.SocketAsyncEventArgsWithId類:該類是一個用戶的連接的最小單元,也就是說對一個用戶來說有兩個SocketAsyncEventArgs對象,這兩個對象是一樣的,但是有一個用來發(fā)送消息,一個接收消息,這樣做的目的是為了實現(xiàn)雙工通訊,提高用戶體驗。默認(rèn)的用戶標(biāo)識是"-1”,狀態(tài)是false表示不可用

01 internal sealed class SocketAsyncEventArgsWithId:IDisposable
02 {
03 private string uid = "-1";
04 private bool state = false;
05 private MySocketAsyncEventArgs receivesaea;
06 private MySocketAsyncEventArgs sendsaea;
07 internal string UID
08 {
09 get { return uid; }
10 set
11 {
12 uid = value;
13 ReceiveSAEA.UID = value;
14 SendSAEA.UID = value;
15 }
16 }
17 }
UID:用戶標(biāo)識,跟MySocketAsyncEventArgs的UID是一樣的,在對SocketAsycnEventArgsWithId的UID屬性賦值的時候也對MySocketAsyncEventArgs的UID屬性賦值。
State:表示連接的可用與否,一旦連接被實例化放入連接池后State即變?yōu)門rue

3.SocketAsyncEventArgsPool類:這個類才是真正的連接池類,這個類真正的為server提供一個可用的用戶連接,并且維持這個連接直到用戶斷開,并把不用的連接放回連接池中供下一用戶連接。

這個類是最核心的東西了,當(dāng)然它設(shè)計的好壞影響著總體性能的好壞,它的各項操作也可能成為整個服務(wù)器性能的瓶頸。Pool包含有幾個成員:

  • Stack<SocketAsyncEventArgsWithId> pool : 從字面意思上就知道這是一個連接棧,用來存放空閑的連接的,使用時pop出來,使用完后push進去。
  • IDictionary<string, SocketAsyncEventArgsWithId> busypool :這個也很好理解,busypool是一個字典類型的,用來存放正在使用的連接的,key是用戶標(biāo)識,設(shè)計的目的是為了統(tǒng)計在線用戶數(shù)目和查找相應(yīng)用戶的連接,當(dāng)然這是很重要的,為什么設(shè)計成字典類型的,是因為我們查找時遍歷字典的關(guān)鍵字就行了而不用遍歷每一項的UID,這樣效率會有所提高。
  • string[] keys:這是一個存放用戶標(biāo)識的數(shù)組,起一個輔助的功能。
  • Count屬性:返回連接池中可用的連接數(shù)。
  • OnlineUID屬性:返回在線用戶的標(biāo)識列表。
  • Pop(string uid)方法:用于獲取一個可用連接給用戶。
  • Push(SocketAsyncEventArgsWithId item)方法:把一個使用完的連接放回連接池。
  • FindByUID(string uid)方法:查找在線用戶連接,返回這個連接。
  • BusyPoolContains(string uid)方法:判斷某個用戶的連接是否在線。
01 internal sealed class SocketAsyncEventArgsPool:IDisposable
02 {
03 internal Stack<SocketAsyncEventArgsWithId> pool;
04 internal IDictionary<string, SocketAsyncEventArgsWithId> busypool;
05 private string[] keys;
06 internal Int32 Count
07 {
08 get
09 {
10 lock (this.pool)
11 {
12 return this.pool.Count;
13 }
14 }
15 }
16 internal string[] OnlineUID
17 {
18 get
19 {
20 lock (this.busypool)
21 {
22 busypool.Keys.CopyTo(keys, 0);
23 }
24 return keys;
25 }
26 }
27 internal SocketAsyncEventArgsPool(Int32 capacity)
28 {
29 keys = new string[capacity];
30 this.pool = new Stack<SocketAsyncEventArgsWithId>(capacity);
31 this.busypool = new Dictionary<string, SocketAsyncEventArgsWithId>(capacity);
32 }
33 internal SocketAsyncEventArgsWithId Pop(string uid)
34 {
35 if (uid == string.Empty || uid == "")
36 return null;
37 SocketAsyncEventArgsWithId si = null;
38 lock (this.pool)
39 {
40 si = this.pool.Pop();
41 }
42 si.UID = uid;
43 si.State = true;    //mark the state of pool is not the initial step
44 busypool.Add(uid, si);
45 return si;
46 }
47 internal void Push(SocketAsyncEventArgsWithId item)
48 {
49 if (item == null)
50 throw new ArgumentNullException("SocketAsyncEventArgsWithId對象為空");
51 if (item.State == true)
52 {
53 if (busypool.Keys.Count != 0)
54 {
55 if (busypool.Keys.Contains(item.UID))
56 busypool.Remove(item.UID);
57 else
58 throw new ArgumentException("SocketAsyncEventWithId不在忙碌隊列中");
59 }
60 else
61 throw new ArgumentException("忙碌隊列為空");
62 }
63 item.UID = "-1";
64 item.State = false;
65 lock (this.pool)
66 {
67 this.pool.Push(item);
68 }
69 }
70 internal SocketAsyncEventArgsWithId FindByUID(string uid)
71 {
72 if (uid == string.Empty || uid == "")
73 return null;
74 SocketAsyncEventArgsWithId si = null;
75 foreach (string key in this.OnlineUID)
76 {
77 if (key == uid)
78 {
79 si = busypool[uid];
80 break;
81 }
82 }
83 return si;
84 }
85 internal bool BusyPoolContains(string uid)
86 {
87 lock (this.busypool)
88 {
89 return busypool.Keys.Contains(uid);
90 }
91 }
92 }
 Note:這個類的設(shè)計缺陷是使用了太多的lock語句,對對象做了太多的互斥操作,所以我盡量的把lock內(nèi)的語句化簡或挪到lock外部執(zhí)行。

4.BufferManager類:該類是一個管理連接緩沖區(qū)的類,職責(zé)是為每一個連接維持一個接收數(shù)據(jù)的區(qū)域。它的設(shè)計也采用了類似與池的技術(shù),先實例化好多內(nèi)存區(qū)域,并把每一塊的地址放入棧中,每執(zhí)行依次pop時拿出一塊區(qū)域來給SocketAsyncEventArgs對象作為Buffer.

01 internal sealed class BufferManager:IDisposable
02 {
03 private Byte[] buffer;
04 private Int32 bufferSize;
05 private Int32 numSize;
06 private Int32 currentIndex;
07 private Stack<Int32> freeIndexPool;
08 internal Boolean SetBuffer(SocketAsyncEventArgs args)
09 {
10 if (this.freeIndexPool.Count > 0)
11 {
12 args.SetBuffer(this.buffer, this.freeIndexPool.Pop(), this.bufferSize);
13 }
14 else
15 {
16 if ((this.numSize - this.bufferSize) < this.currentIndex)
17 {
18 return false;
19 }
20 args.SetBuffer(this.buffer, this.currentIndex, this.bufferSize);
21 this.currentIndex += this.bufferSize;
22 }
23 return true;
24 }
25 }

 

5.RequestHandler類:這里代碼就不貼了,這個類也比較簡單。比如發(fā)送方要發(fā)送的內(nèi)容為:hello,nice to meet you那么真正發(fā)送的內(nèi)容是:[length=22]hello,nice to meet you,length后的數(shù)字是字符串的長度,接收方接收到消息后根據(jù)長度檢驗和獲取信息。

強烈推薦這篇文章:http://www.cnblogs.com/JimmyZhang/archive/2008/09/16/1291854.html

6.SocketListener類:終于到了最重要的部分了,也是一個對外部真正有意義的類,這個類監(jiān)聽用戶的連接請求并從連接池取出一個可用連接給用戶,并且時刻監(jiān)聽用戶發(fā)來的數(shù)據(jù)并處理。在設(shè)計這個類時為了迎合雙工通信我把監(jiān)聽的任務(wù)放到另一個線程中去,這也是我為什么要給每個用戶兩個SocketAsyncEventArgs的原因。當(dāng)然兩個線程是不夠的還要異步。比較重要的語句我都用粗體標(biāo)注了。socket的方法都是成對出現(xiàn)的,ReceiveAsync對應(yīng)OnReceiveCompleted,SendAsync對應(yīng)OnSendCompleted,所以理解起來也不算太難,只是要注意一點:就是接收和發(fā)送消息是在兩個線程里的。

001 public sealed class SocketListener:IDisposable
002 {
003 /// <summary>
004 /// 緩沖區(qū)
005 /// </summary>
006 private BufferManager bufferManager;
007 /// <summary>
008 /// 服務(wù)器端Socket
009 /// </summary>
010 private Socket listenSocket;
011 /// <summary>
012 /// 服務(wù)同步鎖
013 /// </summary>
014 private static Mutex mutex = new Mutex();
015 /// <summary>
016 /// 當(dāng)前連接數(shù)
017 /// </summary>
018 private Int32 numConnections;
019 /// <summary>
020 /// 最大并發(fā)量
021 /// </summary>
022 private Int32 numConcurrence;
023 /// <summary>
024 /// 服務(wù)器狀態(tài)
025 /// </summary>
026 private ServerState serverstate;
027 /// <summary>
028 /// 讀取寫入字節(jié)
029 /// </summary>
030 private const Int32 opsToPreAlloc = 1;
031 /// <summary>
032 /// Socket連接池
033 /// </summary>
034 private SocketAsyncEventArgsPool readWritePool;
035 /// <summary>
036 /// 并發(fā)控制信號量
037 /// </summary>
038 private Semaphore semaphoreAcceptedClients;
039 /// <summary>
040 /// 通信協(xié)議
041 /// </summary>
042 private RequestHandler handler;
043 /// <summary>
044 /// 回調(diào)委托
045 /// </summary>
046 /// <param name="IP"></param>
047 /// <returns></returns>
048 public delegate string GetIDByIPFun(string IP);
049 /// <summary>
050 /// 回調(diào)方法實例
051 /// </summary>
052 private GetIDByIPFun GetIDByIP;
053 /// <summary>
054 /// 接收到信息時的事件委托
055 /// </summary>
056 /// <param name="info"></param>
057 public delegate void ReceiveMsgHandler(string uid, string info);
058 /// <summary>
059 /// 接收到信息時的事件
060 /// </summary>
061 public event ReceiveMsgHandler OnMsgReceived;
062 /// <summary>
063 /// 開始監(jiān)聽數(shù)據(jù)的委托
064 /// </summary>
065 public delegate void StartListenHandler();
066 /// <summary>
067 /// 開始監(jiān)聽數(shù)據(jù)的事件
068 /// </summary>
069 public event StartListenHandler StartListenThread;
070 /// <summary>
071 /// 發(fā)送信息完成后的委托
072 /// </summary>
073 /// <param name="successorfalse"></param>
074 public delegate void SendCompletedHandler(string uid,string exception);
075 /// <summary>
076 /// 發(fā)送信息完成后的事件
077 /// </summary>
078 public event SendCompletedHandler OnSended;
079 /// <summary>
080 /// 獲取當(dāng)前的并發(fā)數(shù)
081 /// </summary>
082 public Int32 NumConnections
083 {
084 get { return this.numConnections; }
085 }
086 /// <summary>
087 /// 最大并發(fā)數(shù)
088 /// </summary>
089 public Int32 MaxConcurrence
090 {
091 get { return this.numConcurrence; }
092 }
093 /// <summary>
094 /// 返回服務(wù)器狀態(tài)
095 /// </summary>
096 public ServerState State
097 {
098 get
099 {
100 return serverstate;
101 }
102 }
103 /// <summary>
104 /// 獲取當(dāng)前在線用戶的UID
105 /// </summary>
106 public string[] OnlineUID
107 {
108 get { return readWritePool.OnlineUID; }
109 }
110 /// <summary>
111 /// 初始化服務(wù)器端
112 /// </summary>
113 /// <param name="numConcurrence">并發(fā)的連接數(shù)量(1000以上)</param>
114 /// <param name="receiveBufferSize">每一個收發(fā)緩沖區(qū)的大小(32768)</param>
115 public SocketListener(Int32 numConcurrence, Int32 receiveBufferSize, GetIDByIPFun GetIDByIP)
116 {
117 serverstate = ServerState.Initialing;
118 this.numConnections = 0;
119 this.numConcurrence = numConcurrence;
120 this.bufferManager = new BufferManager(receiveBufferSize * numConcurrence * opsToPreAlloc, receiveBufferSize);
121 this.readWritePool = new SocketAsyncEventArgsPool(numConcurrence);
122 this.semaphoreAcceptedClients = new Semaphore(numConcurrence, numConcurrence);
123 handler = new RequestHandler();
124 this.GetIDByIP = GetIDByIP;
125 }
126 /// <summary>
127 /// 服務(wù)端初始化
128 /// </summary>
129 public void Init()
130 {
131 this.bufferManager.InitBuffer();
132 SocketAsyncEventArgsWithId readWriteEventArgWithId;
133 for (Int32 i = 0; i < this.numConcurrence; i++)
134 {
135 readWriteEventArgWithId = new SocketAsyncEventArgsWithId();
136 readWriteEventArgWithId.ReceiveSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceiveCompleted);
137 readWriteEventArgWithId.SendSAEA.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
138 //只給接收的SocketAsyncEventArgs設(shè)置緩沖區(qū)
139 this.bufferManager.SetBuffer(readWriteEventArgWithId.ReceiveSAEA);
140 this.readWritePool.Push(readWriteEventArgWithId);
141 }
142 serverstate = ServerState.Inited;
143 }
144 /// <summary>
145 /// 啟動服務(wù)器
146 /// </summary>
147 /// <param name="data">端口號</param>
148 public void Start(Object data)
149 {
150 Int32 port = (Int32)data;
151 IPAddress[] addresslist = Dns.GetHostEntry(Environment.MachineName).AddressList;
152 IPEndPoint localEndPoint = new IPEndPoint(addresslist[addresslist.Length - 1], port);
153 this.listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
154 if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
155 {
156 this.listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
157 this.listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
158 }
159 else
160 {
161 this.listenSocket.Bind(localEndPoint);
162 }
163 this.listenSocket.Listen(100);
164 this.StartAccept(null);
165 //開始監(jiān)聽已連接用戶的發(fā)送數(shù)據(jù)
166 StartListenThread();
167 serverstate = ServerState.Running;
168 mutex.WaitOne();
169 }
170 /// <summary>
171 /// 開始監(jiān)聽線程的入口函數(shù)
172 /// </summary>
173 public void Listen()
174 {
175 while (true)
176 {
177 string[] keys = readWritePool.OnlineUID;
178 foreach (string uid in keys)
179 {
180 if (uid != null && readWritePool.busypool[uid].ReceiveSAEA.LastOperation != SocketAsyncOperation.Receive)
181 {
182 Boolean willRaiseEvent = (readWritePool.busypool[uid].ReceiveSAEA.UserToken as Socket).ReceiveAsync(readWritePool.busypool[uid].ReceiveSAEA);
183 if (!willRaiseEvent)
184 ProcessReceive(readWritePool.busypool[uid].ReceiveSAEA);
185 }
186 }
187 }
188 }
189 /// <summary>
190 /// 發(fā)送信息
191 /// </summary>
192 /// <param name="uid">要發(fā)送的用戶的uid</param>
193 /// <param name="msg">消息體</param>
194 public void Send(string uid, string msg)
195 {
196 if (uid == string.Empty || uid == "" || msg == string.Empty || msg == "")
197 return;
198 SocketAsyncEventArgsWithId socketWithId = readWritePool.FindByUID(uid);
199 if (socketWithId == null)
200 //說明用戶已經(jīng)斷開
201 //100   發(fā)送成功
202 //200   發(fā)送失敗
203 //300   用戶不在線
204 //其它  表示異常的信息
205 OnSended(uid, "300");
206 else
207 {
208 MySocketAsyncEventArgs e = socketWithId.SendSAEA;
209 if (e.SocketError == SocketError.Success)
210 {
211 int i = 0;
212 try
213 {
214 string message = @"[lenght=" + msg.Length + @"]" + msg;
215 byte[] sendbuffer = Encoding.Unicode.GetBytes(message);
216 e.SetBuffer(sendbuffer, 0, sendbuffer.Length);
217 Boolean willRaiseEvent = (e.UserToken as Socket).SendAsync(e);
218 if (!willRaiseEvent)
219 {
220 this.ProcessSend(e);
221 }
222 }
223 catch (Exception ex)
224 {
225 if (i <= 5)
226 {
227 i++;
228 //如果發(fā)送出現(xiàn)異常就延遲0.01秒再發(fā)
229 Thread.Sleep(10);
230 Send(uid, msg);
231 }
232 else
233 {
234 OnSended(uid, ex.ToString());
235 }
236 }
237 }
238 else
239 {
240 OnSended(uid, "200");
241 this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
242 }
243 }
244 }
245 /// <summary>
246 /// 停止服務(wù)器
247 /// </summary>
248 public void Stop()
249 {
250 if(listenSocket!=null)
251 listenSocket.Close();
252 listenSocket = null;
253 Dispose();
254 mutex.ReleaseMutex();
255 serverstate = ServerState.Stoped;
256 }
257 private void StartAccept(SocketAsyncEventArgs acceptEventArg)
258 {
259 if (acceptEventArg == null)
260 {
261 acceptEventArg = new SocketAsyncEventArgs();
262 acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
263 }
264 else
265 acceptEventArg.AcceptSocket = null;
266 this.semaphoreAcceptedClients.WaitOne();
267 Boolean willRaiseEvent = this.listenSocket.AcceptAsync(acceptEventArg);
268 if (!willRaiseEvent)
269 {
270 this.ProcessAccept(acceptEventArg);
271 }
272 }
273 private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
274 {
275 this.ProcessAccept(e);
276 }
277 private void ProcessAccept(SocketAsyncEventArgs e)
278 {
279 if (e.LastOperation != SocketAsyncOperation.Accept)    //檢查上一次操作是否是Accept,不是就返回
280 return;
281 if (e.BytesTransferred <= 0)    //檢查發(fā)送的長度是否大于0,不是就返回
282 return;
283 string UID = GetIDByIP((e.AcceptSocket.RemoteEndPoint as IPEndPoint).Address.ToString());   //根據(jù)IP獲取用戶的UID
284 if (UID == string.Empty || UID == null || UID == "")
285 return;
286 if (readWritePool.BusyPoolContains(UID))    //判斷現(xiàn)在的用戶是否已經(jīng)連接,避免同一用戶開兩個連接
287 return;
288 SocketAsyncEventArgsWithId readEventArgsWithId = this.readWritePool.Pop(UID);
289 readEventArgsWithId.ReceiveSAEA.UserToken = e.AcceptSocket;
290 readEventArgsWithId.SendSAEA.UserToken = e.AcceptSocket;
291 Interlocked.Increment(ref this.numConnections);
292 this.StartAccept(e);
293 }
294 private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
295 {
296 ProcessReceive(e);
297 }
298 private void OnSendCompleted(object sender, SocketAsyncEventArgs e)
299 {
300 ProcessSend(e);
301 }
302 private void ProcessReceive(SocketAsyncEventArgs e)
303 {
304 if (e.LastOperation != SocketAsyncOperation.Receive)
305 return;
306 if (e.BytesTransferred > 0)
307 {
308 if (e.SocketError == SocketError.Success)
309 {
310 Int32 byteTransferred = e.BytesTransferred;
311 string received = Encoding.Unicode.GetString(e.Buffer, e.Offset, byteTransferred);
312 //檢查消息的準(zhǔn)確性
313 string[] msg = handler.GetActualString(received);
314 foreach (string m in msg)
315 OnMsgReceived(((MySocketAsyncEventArgs)e).UID, m);
316 //可以在這里設(shè)一個停頓來實現(xiàn)間隔時間段監(jiān)聽,這里的停頓是單個用戶間的監(jiān)聽間隔
317 //發(fā)送一個異步接受請求,并獲取請求是否為成功
318 Boolean willRaiseEvent = (e.UserToken as Socket).ReceiveAsync(e);
319 if (!willRaiseEvent)
320 ProcessReceive(e);
321 }
322 }
323 else
324 this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
325 }
326 private void ProcessSend(SocketAsyncEventArgs e)
327 {
328 if (e.LastOperation != SocketAsyncOperation.Send)
329 return;
330 if (e.BytesTransferred > 0)
331 {
332 if (e.SocketError == SocketError.Success)
333 OnSended(((MySocketAsyncEventArgs)e).UID, "100");
334 else
335 OnSended(((MySocketAsyncEventArgs)e).UID, "200");
336 }
337 else
338 this.CloseClientSocket(((MySocketAsyncEventArgs)e).UID);
339 }
340 private void CloseClientSocket(string uid)
341 {
342 if (uid == string.Empty || uid == "")
343 return;
344 SocketAsyncEventArgsWithId saeaw = readWritePool.FindByUID(uid);
345 if (saeaw == null)
346 return;
347 Socket s = saeaw.ReceiveSAEA.UserToken as Socket;
348 try
349 {
350 s.Shutdown(SocketShutdown.Both);
351 }
352 catch (Exception)
353 {
354 //客戶端已經(jīng)關(guān)閉
355 }
356 this.semaphoreAcceptedClients.Release();
357 Interlocked.Decrement(ref this.numConnections);
358 this.readWritePool.Push(saeaw);
359 }
360 #region IDisposable Members
361 public void Dispose()
362 {
363 bufferManager.Dispose();
364 bufferManager = null;
365 readWritePool.Dispose();
366 readWritePool = null;
367 }
368 #endregion
369 }
 
關(guān)于所有的類已經(jīng)介紹完了,相信各位都已經(jīng)很明白了,如果不是太清楚就看源代碼,別忘了源代碼是最好的文檔!

當(dāng)然這個2.0仍然還有很多缺陷,比如職責(zé)劃分不太OO,運行不太穩(wěn)定,處理異常能力較差,處理超負(fù)載的連接能力較差,主動拒絕,可測試性差等,希望大家多給點建議,改進才對啊。

源代碼下載:http://files.cnblogs.com/niuchenglei/socketlib.rar

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Socket連接池
【用SocketAsyncEventArgs 池 線程構(gòu)建服務(wù)器“推”】的源代碼分析1
C# 獲得網(wǎng)頁js執(zhí)行之后的Html代碼(body)部分(修訂版)
C# 簡易異步日志類 [ C# | Log | TextWriterTraceListen...
每日定時自動備份的服務(wù)小工具源碼分享
C#開發(fā)高性能Log Help類設(shè)計開發(fā)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服