小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

【用SocketAsyncEventArgs 池 線程構建服務器“推”】的源代碼分析1

 fatcat916 2012-01-22

【用SocketAsyncEventArgs+池+線程構建服務器“推”】的源代碼分析1

2009-07-24 10:01 by Creason New, 991 visits, 收藏, 編輯
      上一篇文章《用SocketAsyncEventArgs+池+線程構建服務器“推”》給大家展示了一下如何使用已封裝好了的類庫,這回再把源代碼貼出來,大家討論一下做為高性能的服務器“推”或是Socket服務器這個方案是否合適,或是有什么改進的地方。首先謝謝您的閱讀。
      還是先把類圖貼出來,免得大家還得去上一篇文章里看類圖:
類圖
       再依次貼每個類的代碼和說明:
      1.MySocketAsyncEventArgs類:這個類的主要目的就是繼承SocketAsyncEventArgs類,讓它作為封裝連接的類代替?zhèn)鹘y(tǒng)上的SocketAsyncEventArgs類,當然它擴展出UID和Property兩個屬性(看類圖),UID是這個對象對應的用戶的標識,比如張三的連接對象Asocket:MySocketAsyncEventArgs的UID屬性就是張三。Property是這個對象是用來讀數(shù)據(jù)的還是用來寫數(shù)據(jù)的,值為"Receive"or"Send"。當然每個用戶有兩個這樣的對象分別是用于讀和寫。接下來貼代碼:

    
internal sealed class MySocketAsyncEventArgs : SocketAsyncEventArgs
    {
        
internal string UID;
        
private string Property;
        
internal MySocketAsyncEventArgs(string property)
        {
            
this.Property = property;
        }
    }
     2.SocketAsyncEventArgsWithId類:這個類也很簡單,就是保存每一個用戶連接的最小單元。大家還是看代碼吧,很明了。

 1 
 2     internal sealed class SocketAsyncEventArgsWithId
 3     {
 4         private string uid;
 5         internal string UID
 6         {
 7             get { return uid; }
 8             set {
 9                 uid = value;
10                 ReceiveSAEA.UID = value;
11                 SendSAEA.UID = value;
12             }
13         }
14         internal MySocketAsyncEventArgs ReceiveSAEA;
15         internal MySocketAsyncEventArgs SendSAEA;
16 
17         internal SocketAsyncEventArgsWithId()
18         {
19             ReceiveSAEA = new MySocketAsyncEventArgs("Receive");
20             SendSAEA = new MySocketAsyncEventArgs("Send");
21         }
22 
      3.SocketAsyncEventArgsPool類,這就是我們的連接池了,它里面保存著n個用于連接的SocketAsyncEventArgsWithId對象,n=并發(fā)連接數(shù),作為“池”,我用了Stak<SocketAsyncEventArgsWithId>,這樣用到了就Pop,不用了就Push,另外還有一個IDictionary<string, SocketAsyncEventArgsWithId>,這個就是用來存忙碌的連接的,也就是說用戶連接了就把SocketAsyncEventArgsWithId連接對象從Stak里Pop出然后Add進IDictionary,如果用戶不用了這個連接就Push進Stak and 從IDictionary里Remove。為什么還用弄個IDictionary呢?是為了從諸多的以及正在使用的連接里面找出UID為xxx的那個連接,主要是為了FindByUID這個方法。下面看代碼:

 1 
 2     internal sealed class SocketAsyncEventArgsPool
 3     {
 4         internal Stack<SocketAsyncEventArgsWithId> pool;
 5         internal IDictionary<string, SocketAsyncEventArgsWithId> busypool;
 6         internal SocketAsyncEventArgsPool(Int32 capacity)
 7         {
 8             this.pool = new Stack<SocketAsyncEventArgsWithId>(capacity);
 9             this.busypool = new Dictionary<string, SocketAsyncEventArgsWithId>();
10         }
11         internal Int32 Count
12         {
13             get { return this.pool.Count; }
14         }
15         internal SocketAsyncEventArgsWithId Pop()
16         {
17             lock (this.pool)
18             {
19                 SocketAsyncEventArgsWithId argsid = this.pool.Pop();
20                 return argsid;
21             }
22         }
23         internal void Push(SocketAsyncEventArgsWithId item)
24         {
25             if (item == null)
26                 throw new ArgumentNullException("SocketAsyncEventArgs對象為空");
27             lock (this.pool)
28             {
29                 if(busypool.Keys.Count!=0)
30                     if(busypool.Keys.Contains(item.UID))
31                         busypool.Remove(item.UID);
32                 item.UID = null;
33                 this.pool.Push(item);
34             }
35         }
36         internal SocketAsyncEventArgsWithId FindByUID(string uid)
37         {
38             SocketAsyncEventArgsWithId SI = null;
39             foreach (string key in busypool.Keys)
40             {
41                 if (key == uid)
42                 {
43                     SI = busypool[uid];
44                     break;
45                 }
46             }
47             return SI;
48         }
49 
      4.BufferManager類,這個就是為每一個SocketAsyncEventArgs對象分配緩沖區(qū)的,當然只給讀的分配緩沖區(qū),寫的就不必了。該類也很簡單,代碼比口舌更好。

 1 
 2     internal sealed class BufferManager
 3     {
 4         private Byte[] buffer;
 5         private Int32 bufferSize;
 6         private Int32 numSize;
 7         private Int32 currentIndex;
 8         private Stack<Int32> freeIndexPool;
 9 
10         internal BufferManager(Int32 numSize, Int32 bufferSize)//分別為緩沖區(qū)的總數(shù)和分配給每一個連接的大小
11         {
12             this.bufferSize = bufferSize;
13             this.numSize = numSize;
14             this.currentIndex = 0;
15             this.freeIndexPool = new Stack<Int32>();
16         }
17 
18         internal void FreeBuffer(SocketAsyncEventArgs args)
19         {
20             this.freeIndexPool.Push(args.Offset);
21             args.SetBuffer(null00);
22         }
23         internal void InitBuffer()
24         {
25             this.buffer = new Byte[this.numSize];
26         }
27         internal Boolean SetBuffer(SocketAsyncEventArgs args)
28         {
29             if (this.freeIndexPool.Count > 0)
30             {
31                 args.SetBuffer(this.buffer, this.freeIndexPool.Pop(), this.bufferSize);
32             }
33             else 
34             {
35                 if ((this.numSize - this.bufferSize) < this.currentIndex)
36                 {
37                     return false;
38                 }
39                 args.SetBuffer(this.buffer, this.currentIndex, this.bufferSize);
40                 this.currentIndex += this.bufferSize;
41             }
42             return true;
43         }
44 
      5.RequestHandler類,這個類就是處理發(fā)送和接受的字符串的,大家知道Socket經(jīng)常會出現(xiàn)這么一種情況,client先后發(fā)送A,B兩條信息,有可能A和B的一半先到server端了,原因是緩沖區(qū)和tcp的機制,而剩下的一半B就要等下一次發(fā)送,那我們作為接收的是不是很痛苦啊,所以做了一個處理,就是在發(fā)送的字符串前加上”長度頭“,比如我們發(fā)送"hello world",那么真正發(fā)送的是"[length=11]hello world",接收到這條信息之后就要檢查信息的長度和頭是否一致,否則等待下一次信息到來再處理接收未完成的信息。如果還不明白就看這篇文章。

 1 
 2     public class RequestHandler
 3     {
 4         private string temp = string.Empty;
 5         public string[] GetActualString(string input)
 6         {
 7             return GetActualString(input, null);
 8         }
 9         private string[] GetActualString(string input, List<string> outputList)
10         {
11             if (outputList == null)
12                 outputList = new List<string>();
13             if (!String.IsNullOrEmpty(temp))
14                 input = temp + input;
15             string output = "";
16             string pattern = @"(?<=^\[length=)(\d+)(?=\])";
17             int length;
18             if (Regex.IsMatch(input, pattern))
19             {
20                 Match m = Regex.Match(input, pattern);
21                 length = Convert.ToInt32(m.Groups[0].Value);
22                 int startIndex = input.IndexOf(']'+ 1;
23                 output = input.Substring(startIndex);
24                 if (output.Length == length)
25                 {
26                     outputList.Add(output);
27                     temp = "";
28                 }
29                 else if (output.Length < length)
30                 {
31                     temp = input;
32                 }
33                 else if (output.Length > length)
34                 {
35                     output = output.Substring(0, length);
36                     outputList.Add(output);
37                     temp = "";
38                     input = input.Substring(startIndex + length);
39                     GetActualString(input, outputList);
40                 }
41             }
42             else
43             {
44                 temp = input;
45             }
46             return outputList.ToArray();
47         }
48 
      至于SocketListener和SocketClient由于代碼比較多,放到下次吧。

      相關文章:  http://www.cnblogs.com/jeriffe/articles/1407603.html     

                       http://www.cnblogs.com/chuncn/archive/2009/06/22/1508018.html

                       http://www.cnblogs.com/dabing/archive/2009/07/10/1520586.html

                       http://www.cnblogs.com/JimmyZhang/archive/2008/09/16/1291854.html

      附上源代碼:下載源代碼    http://files.cnblogs.com/niuchenglei/SocketLib.zip

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約