Visual C#中P2P應用程式的實現
P2P,即英文Peer-to-Peer的縮寫,中譯為對等互聯或點對點技術。講到P2P,人們就會想起Napster,Napster讓人們認識到了P2P技術的威力,P2P技術也就通過Napster進入了大多數使用者的視野,Napster的音樂檔案交換功能是P2P的一個主要應用。P2P技術可以讓使用者可以直接連線到其他使用者的計算機,進行檔案共享與交換。同時P2P在深度搜尋、分佈計算、協同工作等方面也大有用途。
簡單地說,P2P就是一種用於不同PC使用者之間,不經過中繼裝置直接交換資料或服務的技術,它允許Internet使用者直接使用對方的檔案。每個人可以直接連線到其他使用者的計算機,並進行檔案的交換,而不需要連線到伺服器上再進行瀏覽與下載。因為消除了中間環節,P2P技術使得網路上的溝通變得更容易、更直接。P2P改變了Internet現在的以大網站為中心的狀態、重返"非中心化",並把權力交還給使用者。從某種意義上講,P2P體現了Internet的本質。在網路尚未發展成為現在的Web之前,網民就是利用所謂的"佈告板"等渠道彼此直接交換資訊和檔案。
目前Internet的儲存模式是"內容位於中心",而P2P技術的運用將使Internet上的內容向邊緣移動。這將帶來以下改變:首先,客戶不再需要將檔案上傳到伺服器,而只需要使用P2P與其他計算機進行共享;其次,使用P2P技術的計算機不需要固定的IP地址和永久的Internet連線,這使得佔有極大比例的撥號上網使用者也可以享受P2P帶來的變革。
理解P2P技術方面的最好方法是仔細觀察並理解一個實際的P2P應用程式。C#作為微軟.Net戰略的重要棋子,對網路程式設計提供了很好的支援和優化。本文就通過一個程式,向大家介紹一下C#下的P2P程式設計的方法和實現機理。本文的這個程式雖然不是很有用,但卻很直觀地給出了P2P(點對點)程式設計以及套介面程式設計的一些基本知識和概念。它是建立在TcpListener以及TcpClient這兩個類基礎上的,除外還有相應的輸入和輸出控制。實現的原理也比較簡單,但是用到了P2P技術重返"非中心化"的基本原則。簡言之,用這個程式可以在網路中傳送、接受資訊,任何一臺計算機既可以作為伺服器端,又可以作為客戶端。程式共用到了四個類:一個Listener類(用來監聽新的連線)、一個Sender類(用來傳送資訊)、一個Inputhandler類(用來控制輸入)、一個Initialize類(用來完成初始化工作)。下面,我先給大家介紹一下這四個類,最後再給出程式的具體實現方法。
二.基本類介紹
1.Listener類:
Listener類是用來監聽新的連線。當它的一個物件被建立並開啟後,該物件就開始不斷監聽來自網路中的連線請求。一旦有了一個連線請求,該物件就設法建立連線並取得它的位元組流進而轉化成字串顯示在控制檯中。當一個連線結束後,該物件就繼續進行監聽來自網路中的連線請求。
程式碼以及註釋如下:
namespace P2PTest{
using System; using System.Net.Sockets;
using System.Threading; public class Listener
{
private Thread th;
private TcpListener tcpl;
public bool listenerRun = true;//listenerRun為true,表示可以接受連線請求,false則為結束程式
public Listener()//建構函式
{
th = new Thread(new ThreadStart(Listen));//新建一個用於監聽的執行緒
th.Start();//開啟新執行緒
}
public void Stop(){
tcpl.Stop();
th.Abort();//終止執行緒
}
private void Listen(){
try
{
tcpl = new TcpListener(5656);//在5656埠新建一個TcpListener物件
tcpl.Start();
Console.WriteLine("started listening..");
while(listenerRun)//開始監聽
{
Socket s = tcpl.AcceptSocket();
string remote = s.RemoteEndPoint.ToString();
Byte[] stream = new Byte[80];
int i=s.Receive(stream);//接受連線請求的位元組流
string msg = "" + System.Text.Encoding.UTF8.GetString(stream);
Console.WriteLine(msg);//在控制檯顯示字串
}
}
catch(System.Security.SecurityException)
{
Console.WriteLine("firewall says no no to application - application cries..");
}
catch(Exception)
{
Console.WriteLine("stoped listening..");
}
}
}
}
對Listen()函式的補充說明:
這個函式是Listener類的核心部分。該函式首先被建構函式呼叫。只要布林值listenerRun為true,我們就可以在埠5656建立並開始一個Tcp監聽物件TcpListener進行監聽網路中的連線請求,而一旦listenerRun被置為false,則表示程式結束了。在迴圈體內部,我們先接受一個連線,用s.RemoteEndPoint獲得它的IP地址並獲得其位元組流。根據獲得的位元組流,我們用UTF8編碼將它轉化為字串。最後,我們就在控制檯中顯示獲得的字串。
對於catch語句,第一個塊捕獲一個可能由防火牆引起的例外。因為對於防火牆而言,它可能認為這是一個特洛依木馬或是儒蟲病毒什麼的,所以就會拒絕通過。解決辦法就是重新配置防火牆。第二個塊用於捕獲一般的例外,比如當我們呼叫了stop()函式後,我們銷燬了TcpListener物件,那就自然不可能再進行監聽了。
2.Sender類:
Sender類就一個函式,所以是相當簡單的。
程式碼以及註釋如下:
namespace P2PTest {
using System;
using System.IO;
using System.Net.Sockets;
public class Sender
{
public void Send(string[] aInput)
{
string stream = ""; //獲得要傳送的資訊
for(int i=2; i {
stream += aInput[i] + " ";
}
try
{
TcpClient tcpc = new TcpClient(aInput[1], 5656); //在5656埠新建一個TcpClient物件
NetworkStream tcpStream = tcpc.GetStream();
StreamWriter reqStreamW = new StreamWriter(tcpStream);
reqStreamW.Write(stream);
reqStreamW.Flush();//傳送資訊
tcpStream.Close();
tcpc.Close();
}
catch(Exception)
{
Console.WriteLine("connection refused by target computer");
}
}
}
}
對Send()函式的補充說明:
Send(string[] aInput)函式將一個陣列作為引數。陣列的第一個元素Send(aInput[0])必須包含"send"這個字,否則Sender物件不會被建立(更多內容在InputHandler類中);第二個元素包含了目標計算機的IP地址;剩下的就是要傳送的內容資訊了。
在try塊中,我們根據遠端計算機的IP地址在埠5656(要確保埠號統一)建立了一個TcpClient物件。然後,我們建立一個NetworkStream和一個StremWriter物件來傳送我們的資訊。在catch塊中,我們用它來捕獲一般的例外,比如遠端計算機拒絕連線請求、網路不通什麼的。
3.InputHandler類:
InputHandler類主要用來控制使用者輸入。
程式碼以及註釋如下:
namespace P2PTest {
using System;
public class InputHandler
{
public bool appRun = true;//當appRun為false時,程式結束
public InputHandler()
{
Console.WriteLine("type help for a list of commands.");
Input();
}
private static Listener li;//一個靜態的Listener物件
private string inparam;
private string[] aInput;//陣列aInput用於接受使用者輸入的資訊
public void Input() {
while(appRun)
{
inparam = Console.ReadLine();
aInput = inparam.Split(' '); //將inparam分割的目的是為了獲得字串中的第一個字,從而執行以下不同的命令
switch(aInput[0]) {
case "send"://如果是"send",則新建一個Sender物件併傳送資訊
Sender se = new Sender();
se.Send(aInput); break;
case "start"://如果是"start",則新的開始監聽
try {
li.listenerRun = false;
li.Stop();
}
catch(NullReferenceException) { ; }
finally {
li = new Listener();
}
break;
case "stop"://如果是"stop",則停止監聽
try {
li.listenerRun = false;
li.Stop();
}
catch(NullReferenceException) { ; }
break;
case "exit"://退出程式
try {
li.listenerRun = false;
li.Stop();
} catch(NullReferenceException) { ; }
finally {
appRun = false;
}
break;
case "help"://顯示幫助資訊
Console.WriteLine("Commands:");
Console.WriteLine("start: starts the listener");
Console.WriteLine("stop: stops the listener if started");
Console.WriteLine("send: send sends a message");
Console.WriteLine("exit: exits the application");
Console.WriteLine("help: you already know");
break;
default: Console.WriteLine("Invalid command");
break;
}
}
}
}
}
對InputHandler類的補充說明:
該類中有一個靜態的Listener物件li,一旦計算機執行此程式並執行"start"操作,該計算機就可以成為網路中的伺服器來監聽其他計算機的連線請求。而該類的核心部分是一個switch case語句系列,通過不同的操作,我們可以使計算機扮演不同的角色:"send"操作表明該計算機相對目的計算機而言成了客戶端;而"start"操作就將計算機自身置為伺服器端,這正體現了P2P的既是伺服器端又是客戶端的"非中心化"的原則;同時程式也提供了一些其他的輔助操作。
4.Initialize類:
Initialize類進行程式的初始化工作,它新建了一個InputHandler物件,只要該物件的布林值appRun為true,就一直執行之,直到該值為false,程式退出。
程式碼以及註釋如下:
namespace P2PTest {
using System;
public class Init
{
public static void Main() {
InputHandler ih = new InputHandler();//新建一個InputHandler物件
while(ih.appRun);//直到ih.appRun為false,程式退出
Console.WriteLine("exiting..");
}
}
}
到此為止,四個類已經介紹完畢,我想大家也早已等不及了吧,下面就簡單給大家介紹一下具體實現程式的方法。
三.實現方法
首先,開啟Visual Studio.Net,新建一個名為P2Ptest的控制檯應用程式的Visual C#專案,圖示如下:
圖1
其次,將以上四個類分別儲存為四個檔案:listener.cs,sender.cs,inputHandler.cs,initialize.cs。然後將這四個檔案新增到當前的工程中,同時把原有的主檔案刪除即可(因為在initialize.cs中已經有主函式了)。
最後,按Ctrl+F5即可執行程式了。
為了進行測試,我們需要開啟兩個P2Ptest程式,一個作為伺服器端,另一個作為客戶端。伺服器端的圖示如下(此時已經開始監聽了):
圖2
客戶端的圖示如下(輸入命令列:send 10.85.7.79 Hello,I'm Pitt.Can you hear me?):
圖3
再看伺服器端的情況,圖示如下:
圖4
從圖示可以看到伺服器端已經收到訊息了。同時,只要客戶端也開啟了監聽功能,伺服器端也就能向客戶端傳送資訊了。這樣它們的關係就不再是伺服器-客戶機的關係了,而是Peer-to-Peer的關係了。
四.總結
現在一個很基本的P2P應用程式以及完成,通過它,我們可以利用P2P技術的基本特性實現點對點通訊。通過這個程式,我相信大家對C#下的P2P程式設計應該有了大致的瞭解。對於這個程式,不足的一點是功能比較簡單,只可以傳送、接受資訊,而且還是基於控制檯的,讀者可以試著開發出功能更強大的基於Windows Forms的P2P應用程式。
最後,筆者希望能通過此文喚起大家對P2P技術的興趣。因為P2P身後所蘊藏著的無比的創造力使人們對未來網際網路充滿了美好的憧憬,現在世界範圍的P2P應用熱潮也是一浪高過一浪。在可以預見的未來,隨著對P2P研究的進一步深入和關注P2P的群體逐漸增多,P2P必將進入一個飛速發展的新時期。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-545262/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Visual C#託管Socket的實現方法C#
- MVC模式在Java Web應用程式中的實現MVC模式JavaWeb
- Thunk程式的實現原理以及在iOS中的應用iOS
- 機器學習之PageRank演算法應用與C#實現(2):球隊排名應用與C#程式碼機器學習演算法C#
- 在應用程式中實現RAS撥號 (轉)
- Thunk程式的實現原理以及在iOS中的應用(二)iOS
- 使用Visual C#實現斷點續傳C#斷點
- Flask 中模組化應用的實現Flask
- Java程式中的代理作用和應用場景及實現Java
- C#實現JWT無狀態驗證的實戰應用C#JWT
- 純C#鉤子實現及應用(轉)C#
- GeneralUpdate實現應用程式更新
- C#基礎系列:實現自己的ORM(反射以及Attribute在ORM中的應用)C#ORM反射
- 在Visual Studio中快速啟動除錯Web應用程式除錯Web
- C#中結構體的應用C#結構體
- C# 控制檯應用程式中輸出彩色字型C#
- 2.3 應用程式容器中的應用程式概述
- 官方水晶報表 .NET 應用程式例項下載 (C#、Visual C++.NET) (轉)C#C++
- C# 程式開發中經常遇到的10條實用的程式碼C#
- C#程式開發中經常遇到的10條實用的程式碼C#
- Visual Studio中的C,C++,C#C++C#
- C#中的ThenBy是如何實現的C#
- 【實驗手冊】使用Visual Studio Code 開發.NET Core應用程式
- iOS應用程式的脫殼實現原理淺析iOS
- 實現雲原生應用程式可移植的夢想
- jQuery實現的JSONP應用程式碼例項jQueryJSON
- C#中Dictionary的內部實現剖析C#
- 在 React 應用程式中實現簡單的頁面檢視跟蹤器React
- PLC程式中的配方應用C程式
- 03. 實現客戶端應用程式客戶端
- js實現開啟應用程式程式碼例項JS
- P2P網路被谷歌用來共享離線安裝應用程式谷歌
- 棧的應用和實現
- C#中實現列舉數C#
- Cookie、Session、JWT在koa中的應用及實現原理CookieSessionJWT
- 商品API資料在電商中的應用與實現API
- HTTP/2特性及其在實際應用中的表現HTTP
- 用margin實現兩列布局中的自適應列