# [C# 網絡編程系列]專題八:P2P編程
引言:
前面的介紹專題中有朋友向我留言說介紹下關于P2P相關的內容的,首先本人對于C#網絡編程也不是什么大牛,因為能力的關系,也只能把自己的一些學習過程和自己的一些學習過程中的理解和大家分享下的,下面就進入正題——P2P(Peer to Peer)編程
**一、P2P的介紹**
首先,現在大家熟知的BT、電驢、迅雷、QQ、MSN和PPlive等都是基于P2P方式實現的軟件,并且對等聯網(Peer to Peer,P2P)將是互聯網的發展方向,因此對于P2P技術的了解顯得非常的重要,下面就來介紹下P2P架構:
在P2P技術之前,我們所有的網絡應用都采用C/S或者B/S架構來實現的,然而在之前C/S架構的應用程序中,客戶端軟件向服務器發出請求,服務器然后對客戶端請求做出響應,在這種情況下,如果客戶端越多,此時服務器的壓力就越大。然而采用P2P技術實現的每臺計算機既是客戶端,也是服務器,他們的功能都是對等的。對于安裝了P2P軟件(如迅雷,QQ等)的計算機加入一個共同的P2P網絡,網絡中的節點之間可以直接進行數據傳輸和通信。
**1.1 P2P架構和C/S架構的比較**
C/S架構有下面的缺點(其實上面的簡單介紹中也講到過):
1\. 服務器負擔過重。當大量用戶訪問C/S系統的服務器時,服務器常常會出現網絡堵塞等現象,這時候,我們可能會通過增加投資提高服務器的硬件性能
2\. 系統穩健性和服務器關聯密切。指的是——如果服務器出現了問題時,整個系統的運行將會癱瘓(感覺是面向對象中經常強調的原則——低耦合原則)
然而P2P具有下面的特點:
1.對等模式
P2P系統中的客戶端能夠同時扮演客戶端和服務器的角色,使兩臺計算機之間能夠不通過服務器直接進行信息分享(QQ中當好友在線的時候發信息時,相信此時是不需要經過服務器轉發的,只有當給離線好友發送消息時,此時應該會先把消息發送到服務器端存儲起來,當好友再次登錄的時候,會和服務器進行連接,服務器會進行判斷是不是給這個用戶的信息來決定是否轉發,QQ軟件的實現屬于混合型P2P結構的, 這個會在后面的P2P系統分類中介紹。)
注:括號中都是我個人的一些理解,如果有什么說錯的地方請大家及時更正我,這樣我會及時的更新以免誤導大家,謝謝大家監督。
2\. 網絡資源的分布式存儲
在C/S架構中,所有客戶端都直接從服務器下載所有數據資源,這樣勢必會加重服務器的負擔,而P2P則改變了以服務器為中心的狀態,使每個節點可以先從服務器上個下載一部分,然后再相互從對方或者其他節點下載其余部分。采用這種方式,當大量客戶端同時下載時,就不會形成網絡堵塞現象了。
**1.2 P2P系統的分類**
使用P2P技術的系統分為兩類:(1)單純型P2P——沒有專用的服務器。安裝了P2P軟件的各個計算機可以直接通信
(2)混合型P2P——有專用的服務器,此時的服務器一般叫索引服務器,此服務器與C/S架構下的服務器不同,在C/S架構下所有資源都存儲在服務器中,所有傳遞的信息都要經過服務器,而在混合型P2P系統中的索引服務器僅僅起到協調和擴展的功能,資源不是全部存儲在服務器上,而是分布在各個電腦上,安裝了P2P軟件的電腦開始全部和索引服務器連接,以便告知自己監聽的IP地址和端口號,然后再通過索引服務器告訴其他與自己連接的電腦,每臺計算機的連接和斷開都通過服務器通知網絡上有聯系的計算機,這樣就減輕了每臺計算機搜索其他計算機的負擔,但是信息的傳遞還是通過點對點的方式來完成(這里可以以QQ為例,當我們電腦上安裝了QQ這類P2P軟件時,安裝了QQ這類軟件的計算機就會加入一個P2P網絡,并且登陸的時候都會與索引服務器建立連接,通過連接來告訴服務器自己的IP地址和端口號,當我們找一個好友聊天時,此時自己的計算機和好友的計算機都會與服務器端口連接,但是要互相發送消息,自己的計算機必須知道好友計算機的IP地址和端口號才可以通信,這樣的工作正是通過索引服務器來告知對方的--指的是告訴自己的計算機好友的計算機的IP地址和端口號,告訴好友的計算機自己的IP地址和端口號,這樣雙方就可以不通過服務器直接通信了。)
**1.3 主流P2P應用分類**
P2P 網絡應用大致可以分為三類—— 1\. 文件共享類,例如迅雷,BT等軟件都是文件共享類的應用
2\. 即時通信類,例如QQ,MSN等軟件都是屬于即時通信類
3\. 多媒體傳輸類,例如在線視頻直播軟件,PPlive等軟件
從上面的分類可以看出,現在網絡上流行的軟件都采用了P2P技術來實現的, 但是它們的實現肯定不是單純的只采用P2P技術來實現的, 而是采用多種技術來實現的, 在下一專題中將介紹利用TCP,UDP和P2P等技術來實現類似QQ的一個即時通信程序,希望通過此程序可以綜合前面專題介紹的內容以及幫助大家對QQ等軟件的實現原理有了解。
**二、P2P的基本原理**
在前面我們對P2P的一些知識進行的簡單的介紹, 通過前面的介紹相信大家對P2P的技術有了一定的了解,但是要自己開發一個P2P的應用當然必須了解P2P技術的實現原理的,下面就介紹下P2P實施的基本原理。
安裝了P2P軟件后,首先雙方要進行通信,必須能夠發現對方(指的就是知道對方的IP地址和端口號),一旦發現了對方后才可以進行通信,所以P2P應用程序一般分為**發現、連接和通信**3個階段。 發現階段負責動態定位通信方的網絡位置;連接階段負責在雙方建立網絡連接,通信階段負責在雙方之間傳輸數據。
**2.1 發現階段**
一臺計算機要和另外一臺計算機通信,必須知道對方的IP地址和監聽端口,否則就無法向對方發送消息。在之前的C/S架構中,服務器的IP地址一般固定不變的,并且提供服務的計算機域名也一般不會改變,所以為了方便客戶端訪問,一些Web服務器在DNS(DNS其實就是域名和IP地址的一個映射)中進行了注冊,客戶機可以利用域名解析機制將服務器域名解析為IP地址,然后在P2P應用中,各個對等節點(計算機或資源)可以隨時加入和隨時離開,并且對等節點的IP地址也不是固定的,所以不能采用DNS的機制來獲取P2P架構中的對等節點的信息。
目前,在單純型P2P中,針對如何發現對等節點,各種P2P技術采用的協議和標準都不一樣,微軟在.net 支持對等名稱解析協議(Peer name Resolution Protocol, PNRP),該協議可以發現對等節點的信息,通過無服務器的解析功能將任何資源解析為一組IP地址和端口號,在后面的實現的簡單程序用的就是這個協議來完成發現階段的。
**2.2 連接和通信階段**
完成對等節點的發現后,接下來就可以根據需要,選擇TCP、UDP或者其他協議完成數據傳輸。如果選擇TCP,則需要先建立連接,再利用該連接傳輸數據,關于TCP的內容可以查看我之前的專題;如果選擇UDP,則無須建立連接,直接在對等節點之間通信就可以了。
**三、.net平臺對P2P編程的支持**
之前在發現階段也介紹了.Net平臺對P2P編程的支持的,然后微軟幫我們已經封裝好了對PNRP協議的實現,這些類在System.Net.PeerToPeer命名空間里(微軟現在很多東西都幫我們封裝了,這樣可以方便我們開發應用程序,感覺微軟的做的東西都是這樣,把程序的實現都幫我們做好了,我們開發程序的時候只要關注業務邏輯就好了的, 這樣做當然有好處也有壞處的, 我覺得好處就是縮短軟件的開發周期,讓花更多的時間去實現軟件真真的業務邏輯方面的東西,不好的地方就是現在的程序員就不能叫程序員,所以園子里面有很多人都稱碼農,這些我自己的觀點了)
**3.1 對等名稱解析協議(PNRP)**
PNRP可以完成對等名稱的注冊和解析(可以和DNS對比來理解)。
**3.1.1 基本概念**
第一個介紹的是對等名稱的概念,我們將每一個網絡資源(包括計算機,P2P應用程序、視頻、Mp3或其他文檔等資源)抽象為對等節點,對等節點名稱當然就是對等節點的名稱。對等節點名稱簡稱為對等名,分為安全的和不安全的兩種形式,不安全的名稱僅由文本字符串組成,任何人都可以注冊一個相同的不安全對等名稱;安全的由一個公鑰/私鑰(代表唯一)對支持,所以使用PNRP注冊時,不會受到欺騙,對等名稱的格式如下:
**Authority.Classifier**
Authority的值取決于該名稱的安全類型。對于不安全的類型,Authority為單字符“0”,而對于安全的對等名稱,Authority由40個十六機制字符組成
Classifier是用戶定義的用于標志對等節點的字符串,最大長度為150個Unicode字符。例如,對等名稱0.PeerNametest1就是一個不安全的對等名稱。
第二個概念就是云(Cloud)的概念,安裝了相同P2P軟件的計算機會加入一個共同的P2P網絡中,才能相互識別各自擁有的資源并順利進行P2P通信。微軟PNPR協議將這個P2P網絡稱為“云”。**云是指一組可以通過P2P網絡相互識別的對等節點及其上資源的集合。**云中的所有對等節點都可以解析注冊到該云中的其他任何資源所在的位置(IP+Port),一個對等節點上的某個資源可以同時注冊到多個云中。
PNPR目前使用了兩種云——本地云和全局云。一個對等名稱若注冊到鏈接一本地云,就意味著只有同一本地網絡上的其他對等節點可以解析該名稱。而注冊到全局云上的對等名稱則允許IPv6互聯網的任何對等節點解析。
注:全局云是基于IPv6協議的,并不支持IPv4,如果不存在IPv6地址,則不會出現全局云,也無法加入全局云。由于現在網上絕大多數應用使用的仍然是IPv4的地址,所以我們通常的P2P編程還用不到全局云,而只能使用默認的本地云。
**3.1.2 名稱注冊**
任何資源要被網絡上的其他計算機識別到,首先必須注冊進P2P網絡,名稱注冊就是將包含對等節點信息的對等名稱發布到云中,以便其他對等節點解析。一個資源如果注冊到云中后,就可以被云中的其他對等節點解析和訪問。
關于名稱注冊的具體內容,在后面的P2P的程序中也會使用的, 相信大家可以通過代碼來進一步理解名稱的注冊,這里就先介紹到這里的
**3.1.3 名稱解析**
名稱解析是指利用對等名稱獲取到云中資源所在對等節點的IP地址和端口號的過程(和DNS解析原理一樣)。**PNPR名稱解析僅能夠注冊到云中的其他對等節點資源,而不能發現自身注冊的資源**
PNPR協議沒有使用索引服務器,所以為了完成解析,云中的每個對等節點都存儲一些PNRP ID的緩存記錄。PNPR緩存中的都含有PNPR ID和應用程序的IP地址和端口號。名稱解析的步驟為——首先在本地計算機對等節點的緩存中查找目標資源,如果沒有,則在緩存中的臨近節點查看,這樣循環下去,直到找到目標資源所在的對等節點位置。
**3.2 PeerToPeer命名空間**
上面主要介紹了PNPR協議的工作過程(相當于是理論部分了),下面就介紹下.net 為我們封裝好PNPR的類的使用。這里就簡單指明幾個常用類的使用,并附上MSDN的鏈接,大家可以直接點鏈接進行查看詳細內容,因為后面的P2P程序中也有具體的使用,所以這里就不一一列出來了。
| 類名 | MSDN鏈接 |
| --- | --- |
| Peer類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.collaboration.peer.aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.collaboration.peer.aspx) |
| Cloud類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.cloud.aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.cloud.aspx) |
| PeerName類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peername.aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peername.aspx) |
| PeerNameRecord類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernamerecord.aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernamerecord.aspx) |
| PeerNameRegistration類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameregistration_members(v=VS.90).aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameregistration_members(v=VS.90).aspx) |
| PeerNameResolver類 | [http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameresolver.aspx](http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameresolver.aspx) |
這些類基本上從類名都可以大致知道他們的用途的,所以在這里就沒有一一介紹的,只是附上了MSDN的鏈接。
**四、實現P2P應用程序**
以上介紹了那么多P2P的相關的知識,主要是為了實現一個自定義的P2P應用程序做準備的,這里就簡單實現了資源發現的一個程序。
核心代碼:
對等名稱的注冊代碼:
```
// 注冊資源
private void btnRegister_Click(object sender, EventArgs e)
{
if (tbxResourceName.Text == "")
{
MessageBox.Show("請輸入發布的資源名!", "提示");
return;
}
// 將資源名注冊到云中
// 具體資源名的結構在博客有介紹
PeerName resourceName = new PeerName(tbxResourceName.Text, PeerNameType.Unsecured);
// 用指定的名稱和端口號初始化PeerNameRegistration類的實例
resourceNameReg[seedCount] = new PeerNameRegistration(resourceName, int.Parse(tbxlocalport.Text));
// 設置在云中注冊的對等名對象的其他信息的注釋
resourceNameReg[seedCount].Comment =resourceName.ToString();
// 設置PeerNameRegistration對象的應用程序定義的二進制數據
resourceNameReg[seedCount].Data = Encoding.UTF8.GetBytes(string.Format("{0}", DateTime.Now.ToString()));
// 在云中注冊PeerName(對等名)
resourceNameReg[seedCount].Start();
seedCount++;
comboxSharelist.Items.Add(resourceName.ToString());
tbxResourceName.Text = "";
}
```
名稱解析代碼(搜索資源):
```
// 搜索資源
private void btnSearch_Click(object sender, EventArgs e)
{
if (tbxSeed.Text == "")
{
MessageBox.Show("請先輸入要尋找的種子資源名", "提示");
return;
}
lstViewOnlinePeer.Items.Clear();
// 初始化要搜索的資源名
PeerName searchSeed = new PeerName("0." + tbxSeed.Text);
// PeerNameResolver類是將節點名解析為PeerNameRecord的值(即將通過資源名來查找資源名所在的地址,包括IP地址和端口號)
// PeerNameRecord用來定于云中的各個節點
PeerNameResolver myresolver = new PeerNameResolver();
// PeerNameRecordCollection表示PeerNameRecord元素的容器
// Resolve方法是同步的完成解析
// 使用同步方法可能會出現界面“假死”現象
// 解決界面假死現象可以采用多線程或異步的方式
// 關于多線程的知識可以參考本人博客中多線程系列我前面UDP編程中有所使用
// 在這里就不列出多線程的使用了,朋友可以自己實現,如果有問題可以留言給我一起討論
PeerNameRecordCollection recordCollection = myresolver.Resolve(searchSeed);
foreach (PeerNameRecord record in recordCollection)
{
foreach(IPEndPoint endpoint in record.EndPointCollection)
{
if (endpoint.AddressFamily.Equals(AddressFamily.InterNetwork))
{
ListViewItem item = new ListViewItem();
item.SubItems.Add(endpoint.ToString());
item.SubItems.Add(Encoding.UTF8.GetString(record.Data));
lstViewOnlinePeer.Items.Add(item);
}
}
}
}
```
運行結果截圖: 為了演示資源發現的效果,所以同時開啟了本程序的3個進程來模擬網絡上對等的3個計算機節點,當在資源名中輸入資源后會在分享下列表中顯示出本地分享的資源,同時在P2P網絡上的其他計算機可以通過資源名稱搜索該資源,將得到的資源名稱和發布時間顯示在ListView控件中,下面是程序的運行結果:

**五、總結**
到這里P2P編程的介紹就結束了, 本專題只是簡單演示了一個資源發現的程序,資源發現是P2P的核心技術,正是因為P2P技術實現了互聯網范圍的資源發現,才使得它被廣泛應用,像我們經常用的下載工具——迅雷,迅雷就是典型采用P2P技術的應用程序,當我們在迅雷頁面中輸入“愛情公寓3”(相當于本專題中種子文本框填的資源名)然后點擊搜索后迅雷會自動啟動“狗狗搜索”并顯示資源鏈接列表,當我們點擊連接就可以進行下載了。不過迅雷肯定不是使用微軟的PNPR,而是迅雷自主研發的與PNPR作用一樣的協議——都是完成解析網絡資源的地址的作用,當然,迅雷軟件中也采用了其他的一些技術,如搜索引擎等。
希望本專題可以幫助大家對P2P技術有所了解,如果有任何的問題都可以通過留言的方式來一起討論,在下一個專題中將介紹實現一個類似QQ的程序。
源碼附上:[http://files.cnblogs.com/zhili/P2PResourceDiscovery.zip](http://files.cnblogs.com/zhili/P2PResourceDiscovery.zip) ,希望覺得有幫助的朋友可以推薦下。謝謝支持
- C# 基礎知識系列
- C# 基礎知識系列 專題一:深入解析委托——C#中為什么要引入委托
- C# 基礎知識系列 專題二:委托的本質論
- C# 基礎知識系列 專題三:如何用委托包裝多個方法——委托鏈
- C# 基礎知識系列 專題四:事件揭秘
- C# 基礎知識系列 專題五:當點擊按鈕時觸發Click事件背后發生的事情
- C# 基礎知識系列 專題六:泛型基礎篇——為什么引入泛型
- C# 基礎知識系列 專題七: 泛型深入理解(一)
- C# 基礎知識系列 專題八: 深入理解泛型(二)
- C# 基礎知識系列 專題九: 深入理解泛型可變性
- C#基礎知識系列 專題十:全面解析可空類型
- C# 基礎知識系列 專題十一:匿名方法解析
- C#基礎知識系列 專題十二:迭代器
- C#基礎知識 專題十三:全面解析對象集合初始化器、匿名類型和隱式類型
- C# 基礎知識系列 專題十四:深入理解Lambda表達式
- C# 基礎知識系列 專題十五:全面解析擴展方法
- C# 基礎知識系列 專題十六:Linq介紹
- C#基礎知識系列 專題十七:深入理解動態類型
- 你必須知道的異步編程 C# 5.0 新特性——Async和Await使異步編程更簡單
- 全面解析C#中參數傳遞
- C#基礎知識系列 全面解析C#中靜態與非靜態
- C# 基礎知識系列 C#中易混淆的知識點
- C#進階系列
- C#進階系列 專題一:深入解析深拷貝和淺拷貝
- C#進階系列 專題二:你知道Dictionary查找速度為什么快嗎?
- C# 開發技巧系列
- C# 開發技巧系列 使用C#操作Word和Excel程序
- C# 開發技巧系列 使用C#操作幻燈片
- C# 開發技巧系列 如何動態設置屏幕分辨率
- C# 開發技巧系列 C#如何實現圖片查看器
- C# 開發技巧 如何防止程序多次運行
- C# 開發技巧 實現屬于自己的截圖工具
- C# 開發技巧 如何使不符合要求的元素等于離它最近的一個元素
- C# 線程處理系列
- C# 線程處理系列 專題一:線程基礎
- C# 線程處理系列 專題二:線程池中的工作者線程
- C# 線程處理系列 專題三:線程池中的I/O線程
- C# 線程處理系列 專題四:線程同步
- C# 線程處理系列 專題五:線程同步——事件構造
- C# 線程處理系列 專題六:線程同步——信號量和互斥體
- C# 多線程處理系列專題七——對多線程的補充
- C#網絡編程系列
- C# 網絡編程系列 專題一:網絡協議簡介
- C# 網絡編程系列 專題二:HTTP協議詳解
- C# 網絡編程系列 專題三:自定義Web服務器
- C# 網絡編程系列 專題四:自定義Web瀏覽器
- C# 網絡編程系列 專題五:TCP編程
- C# 網絡編程系列 專題六:UDP編程
- C# 網絡編程系列 專題七:UDP編程補充——UDP廣播程序的實現
- C# 網絡編程系列 專題八:P2P編程
- C# 網絡編程系列 專題九:實現類似QQ的即時通信程序
- C# 網絡編程系列 專題十:實現簡單的郵件收發器
- C# 網絡編程系列 專題十一:實現一個基于FTP協議的程序——文件上傳下載器
- C# 網絡編程系列 專題十二:實現一個簡單的FTP服務器
- C# 互操作性入門系列
- C# 互操作性入門系列(一):C#中互操作性介紹
- C# 互操作性入門系列(二):使用平臺調用調用Win32 函數
- C# 互操作性入門系列(三):平臺調用中的數據封送處理
- C# 互操作性入門系列(四):在C# 中調用COM組件
- CLR
- 談談: String 和StringBuilder區別和選擇
- 談談:程序集加載和反射
- 利用反射獲得委托和事件以及創建委托實例和添加事件處理程序
- 談談:.Net中的序列化和反序列化
- C#設計模式
- UML類圖符號 各種關系說明以及舉例
- C#設計模式(1)——單例模式
- C#設計模式(2)——簡單工廠模式
- C#設計模式(3)——工廠方法模式
- C#設計模式(4)——抽象工廠模式
- C#設計模式(5)——建造者模式(Builder Pattern)
- C#設計模式(6)——原型模式(Prototype Pattern)
- C#設計模式(7)——適配器模式(Adapter Pattern)
- C#設計模式(8)——橋接模式(Bridge Pattern)
- C#設計模式(9)——裝飾者模式(Decorator Pattern)
- C#設計模式(10)——組合模式(Composite Pattern)
- C#設計模式(11)——外觀模式(Facade Pattern)
- C#設計模式(12)——享元模式(Flyweight Pattern)
- C#設計模式(13)——代理模式(Proxy Pattern)
- C#設計模式(14)——模板方法模式(Template Method)
- C#設計模式(15)——命令模式(Command Pattern)
- C#設計模式(16)——迭代器模式(Iterator Pattern)
- C#設計模式(17)——觀察者模式(Observer Pattern)
- C#設計模式(18)——中介者模式(Mediator Pattern)
- C#設計模式(19)——狀態者模式(State Pattern)
- C#設計模式(20)——策略者模式(Stragety Pattern)
- C#設計模式(21)——責任鏈模式
- C#設計模式(22)——訪問者模式(Vistor Pattern)
- C#設計模式(23)——備忘錄模式(Memento Pattern)
- C#設計模式總結
- WPF快速入門系列
- WPF快速入門系列(1)——WPF布局概覽
- WPF快速入門系列(2)——深入解析依賴屬性
- WPF快速入門系列(3)——深入解析WPF事件機制
- WPF快速入門系列(4)——深入解析WPF綁定
- WPF快速入門系列(5)——深入解析WPF命令
- WPF快速入門系列(6)——WPF資源和樣式
- WPF快速入門系列(7)——深入解析WPF模板
- WPF快速入門系列(8)——MVVM快速入門
- WPF快速入門系列(9)——WPF任務管理工具實現
- ASP.NET 開發
- ASP.NET 開發必備知識點(1):如何讓Asp.net網站運行在自定義的Web服務器上
- ASP.NET 開發必備知識點(2):那些年追過的ASP.NET權限管理
- ASP.NET中實現回調
- 跟我一起學WCF
- 跟我一起學WCF(1)——MSMQ消息隊列
- 跟我一起學WCF(2)——利用.NET Remoting技術開發分布式應用
- 跟我一起學WCF(3)——利用Web Services開發分布式應用
- 跟我一起學WCF(3)——利用Web Services開發分布式應用
- 跟我一起學WCF(4)——第一個WCF程序
- 跟我一起學WCF(5)——深入解析服務契約 上篇
- 跟我一起學WCF(6)——深入解析服務契約 下篇
- 跟我一起學WCF(7)——WCF數據契約與序列化詳解
- 跟我一起學WCF(8)——WCF中Session、實例管理詳解
- 跟我一起學WCF(9)——WCF回調操作的實現
- 跟我一起學WCF(10)——WCF中事務處理
- 跟我一起學WCF(11)——WCF中隊列服務詳解
- 跟我一起學WCF(12)——WCF中Rest服務入門
- 跟我一起學WCF(13)——WCF系列總結
- .NET領域驅動設計實戰系列
- .NET領域驅動設計實戰系列 專題一:前期準備之EF CodeFirst
- .NET領域驅動設計實戰系列 專題二:結合領域驅動設計的面向服務架構來搭建網上書店
- .NET領域驅動設計實戰系列 專題三:前期準備之規約模式(Specification Pattern)
- .NET領域驅動設計實戰系列 專題四:前期準備之工作單元模式(Unit Of Work)
- .NET領域驅動設計實戰系列 專題五:網上書店規約模式、工作單元模式的引入以及購物車的實現
- .NET領域驅動設計實戰系列 專題六:DDD實踐案例:網上書店訂單功能的實現
- .NET領域驅動設計實戰系列 專題七:DDD實踐案例:引入事件驅動與中間件機制來實現后臺管理功能
- .NET領域驅動設計實戰系列 專題八:DDD案例:網上書店分布式消息隊列和分布式緩存的實現
- .NET領域驅動設計實戰系列 專題九:DDD案例:網上書店AOP和站點地圖的實現
- .NET領域驅動設計實戰系列 專題十:DDD擴展內容:全面剖析CQRS模式實現
- .NET領域驅動設計實戰系列 專題十一:.NET 領域驅動設計實戰系列總結