P2P,英文Peer-to-Peer的縮寫,中譯為對等互聯或點對點技術。P2P技術可以讓用戶可以直接連接到其他用戶的計算機,進行文件共享與交換,同時P2P在深度搜索、分布計算、協同工作等方面也大有用途。
簡單地說,P2P就是一種用于不同PC用戶之間,不經過中繼設備直接交換數據或服務的技術,它允許Internet用戶直接使用對方的文件。每個人可以直接連接到其他用戶的計算機,并進行文件的交換,而不需要連接到服務器上再進行瀏覽與下載。
目前Internet的存儲模式是“內容位于中心”,而P2P技術的運用將使Internet上的內容向邊緣移動。這將帶來以下改變:
首先,客戶不再需要將文件上傳到服務器,而只需要使用P2P與其他計算機進行共享;
其次,使用P2P技術的計算機不需要固定的IP地址和永久的Internet連接,這使得占有極大比例的撥號上網用戶也可以享受P2P帶來的變革。
理解P2P技術的最好方法莫過于仔細觀察并理解一個實際的P2P應用程序。C#作為微軟.Net戰略的重要棋子,對網絡編程提供了很好的支持和優化。本文就通過一個程序,向大家介紹一下C#下的P2P編程的方法和實現機理。本文的這個程序不是很有用,但卻很直觀地給出了P2P(點對點)編程以及套接口編程的一些基本知識和概念。它是建立在TcpListener以及TcpClient這兩個類基礎上的。程序實現的原理也比較簡單,但是用到了P2P技術重返“非中心化”的基本原則。簡言之,用這個程序可以在網絡中發送、接受消息,任何一臺計算機既可以作為服務器端,又可以作為客戶端。
系統要求:
1.Widows 2000服務器版操作系統或后續版本的操作系統。
2.Visual Studio.net Framework正式版。
具體方法:
首先,打開VS.net,新建一個C#項目(注意:模板為Windows應用程序),不妨命名為"P2Pchat"。圖示如下:

其次,參照ICQ、OICQ等聊天工具,我們可以將程序的主界面布置成和常見聊天工具的消息發送對話框類似的布局。不過由于程序僅一個主界面,所以還要添加一些諸如“開始監聽”、“停止監聽”等控制按鈕。同時,程序是支持昵稱顯示的。于是,按照這個思想,我們可以開始布置程序的主界面了。首先,往主界面上拖放如下一些控件:兩個Label控件、三個Button控件、三個TextBox控件、一個RichTextBox控件以及一個StatusBar控件。各個控件的屬性設置如下表所示:
Form1 | Text屬性 | P2P聊天工具 |
Label1 | Text屬性 | 目標計算機地址: |
TestSlign屬性 | MiddleCenter | |
Label2 | Text屬性 | 昵稱: |
TextAlign屬性 | MiddleCenter | |
Button1 | Text屬性 | 開始監聽 |
FlatStyle屬性 | Flat | |
Button2 | Text屬性 | 停止監聽 |
FlatStyle屬性 | Flat | |
Enabled屬性 | False | |
Anchor屬性 | Top, Right | |
Button3 | Text屬性 | 發送消息 |
FlatStyle屬性 | Flat | |
Anchor屬性 | Top, Right | |
TextBox1 | Text屬性 | (空) |
Anchor屬性 | Top, Left, Right | |
TextBox2 | Text屬性 | (空) |
Multiline屬性 | True | |
Anchor屬性 | Top, Left, Right | |
TextBox3 | Text屬性 | (空) |
ForeColor屬性 | Firebrick | |
Anchor屬性 | Top, Left, Right | |
RichTextBox1 | Text屬性 | (空) |
ForeColor屬性 | Steelblue | |
ReadOnly屬性 | True | |
Anchor屬性 | Top, Bottom, Left, Right |
注:其中的Anchor屬性是設置窗體上控件布局用的,當窗體大小改變后各個控件如何在窗體上重新分布由該屬性決定,讀者可參考更詳細的介紹文章來理解。
其他屬性為默認即可,最終布置主窗體界面如下所示:

現在到了程序的主體部分,即代碼部分。在給出代碼之前,我想先向大家介紹一下實現的基本原理以及其中的一些邏輯關系。
首先,程序運行后,用戶得先按下“開始監聽”按鈕,按鈕相應事件后,程序就進入了監聽狀態,狀態欄有相應的顯示。這樣,本機就相當于“服務器/客戶機”模式中的服務器了,其他計算機可以連接到本機并向本機發送消息。其他計算機通過該程序連接到本機是通過IP地址來實現的,C#對網絡編程有很好的支持,所以程序員的工作量是比較小的。如此,一臺計算機可以向另一臺發送消息了。然而,這是個P2P程序,所以只要另一臺計算機的用戶也按下"開始監聽"按鈕,那臺計算機也成了這臺計算機的服務器了。于是就實現了消息互發功能,然而真正的服務器是不存在的,每臺計算機都是服務器,每臺計算機同時也是客戶機,這就體現了P2P技術的"非中心化"原則。 最后,筆者希望能通過此文喚起大家對P2P技術的興趣。因為P2P身后所蘊藏著的無比的創造力使人們對未來互聯網充滿了美好的憧憬,現在世界范圍的P2P應用熱潮也是一浪高過一浪。在可以預見的未來,隨著對P2P研究的進一步深入和關注P2P的群體逐漸增多,P2P必將進入一個飛速發展的新時期。然而國內的P2P起步得比較晚,所以更需要有大量的技術研究投入以及足夠的重視以贏得更好的發展。在此,筆者希望國內的P2P能取得輝煌的發展。
程序主要用到了一個Listen()函數和一個Send()函數。前者實現程序的監聽功能,函數實現如下:
函數的主體是一個try-catch語句,try部分又是一個while循環,這表示只要用戶不按"停止監聽"按鈕,程序就會一直處于監聽狀態。監聽的端口是5656,這個端口是可以自己定義的,只要不跟常用的端口混淆就行了。一旦程序接收到遠程計算機的一條消息,就將該消息添加到消息顯示框中(消息顯示框就是那個RichTextBox控件)。函數的catch部分是捕捉一些異常用的,如用戶之間設置了防火墻,就不能彼此通訊了,或是對方已經停止監聽了,那當然就不能向它發送消息了。另一個函數Send()是實現程序發送消息的功能的。函數實現如下:
該函數的主體部分也是一個try-catch語句,它先根據用戶的輸入,建立一個和遠程計算機的連接,注意其端口也為5656,而且必須是5656,這是為了和接收方端口保持一致,這樣對方才能收到這里發送的消息。接著,函數根據用戶在消息輸入框中的內容以及用戶的昵稱向遠程計算機發送消息。這樣,只要網絡無故障、遠程計算機已經處于監聽狀態,它就能接收到這里發送的消息了。當然,這里處于監聽狀態了,遠程的計算機也可以自如地往這里發消息。函數的catch部分也是用于捕捉一些異常的。
同時還要注意的是,由于該程序用到了許多網絡編程所需的對象以及輸入輸出對象,又運用了多線程編程機制,所以在程序的開始出得添加如下一些名字空間:
最后,程序中各個控件的事件處理函數以及完整的代碼請參看文后附帶的源代碼包。程序運行的圖示如下:
現在一個很基本的P2P運用程序以及完成,通過它,我們可以利用P2P技術的基本特性實現點對點通信。通過這個程序,我相信大家對C#下的P2P編程應該有了大致的了解。對于這個程序,不足的一點是功能比較簡單,只可以發送、接受信息,而且不能穿過防火墻進行通訊,讀者可以試著開發出功能更強P2P應用程序。
源代碼下載:立即下載