VisualC#實現UDP協議(一)
發表于:2007-05-26來源:作者:點擊數:
標簽:
一.走進UDP 協議 : UDP(UserDatagramProtocol) 協議 就是“用戶數據報 協議 ”,它是一種無連接的 協議 ,無連接主要是和TCP 協議 相比較的。我們知道當利用TCP 協議 傳送數據的時候,首先必須先建立連接(也就是所謂的握手)才可以傳輸數據。而當計算機
一.走進UDP協議:
UDP(UserDatagramProtocol)協議就是“用戶數據報協議”,它是一種無連接的協議,無連接主要是和TCP協議相比較的。我們知道當利用TCP協議傳送數據的時候,首先必須先建立連接(也就是所謂的握手)才可以傳輸數據。而當計算機利用UDP協議進行數據傳輸的時候,發送方只需要知道對方的IP地址和端口號就可以發送數據,而并不需要進行連接。當然如果你非要進行連接,通過VisualC#也是可以實現的,但前提是要確定連接的遠程主機的端口號處于監聽狀態,否則程序會出現不必要的錯誤,但這是種畫蛇添足的做法,不僅丟失了UDP協議的無連接傳送數據的特點和優點,而且還給程序運行帶來了不安定的因素。所以這種方法并不值得提倡。
由于UDP協議并不需要進行確定的連接,所以編寫基于UDP協議的應用程序比起編寫基于TCP協議的應用程序要簡單些(程序中可以不需要考慮連接和一些異常的捕獲工作)。但同時也給基于UDP協議編寫的程序帶來了一個致命的缺點,UDP由于不提供可靠數據的傳輸,當計算機之間利用UDP協議傳送數據的時候,發送方只管發送數據,而并不確認數據是否被對方接收。這樣就會導致某些UDP協議數據包在傳送的過程中丟失,尤其網絡質量不令人滿意的情況下,丟失數據包的現象會更嚴重。這就是為什么在網絡上傳輸重要數據不采用UDP協議的原因。
但是我們也不能因為這一個缺點就全面否定UDP協議,這是因為雖然利用UDP協議來傳送安全性要求高的數據是不適合的,但對于那些不重要的數據,或者即使丟失若干數據包也不影響整體性的數據,如音頻數據,視頻數據等,采用UDP協議就是一個非常不錯的選擇。如目前網絡流行的很多即時聊天程序,如OICQ和ICQ等,采用的就是UDP協議。同時雖然UDP協議無法保證數據可靠性,但具有對網絡資源開銷較小,數據處理速度快的優點,所以在有些對數據安全性要求不是很高的情況下,采用UDP協議也是一個非常不錯的選擇。
總結一下上面的內容,可見UDP是一種不面向連接的網絡協議,既有其優點,也有其不足,具體如下:
1.基于UDP協議的網絡應用程序,實現起來比較簡單,并且基于UDP協議的網絡應用程序在運行時,由于受到環境影響較小,所以不容易出錯。
2.UDP協議占用網絡資源較少,數據處理較快,所以在網絡中傳送對安全性要求不是十分高數據時,其優點比較明顯。所謂對安全性要求不高的數據,是指那些不重要的數據,或者是即使丟失若干數據,也不影響其整體的數據,如音頻數據等。目前很多流行的網絡應用程序都是基于UDP協議的,如OICQ、ICQ等。
3.由于其不是面向連接的網絡協議,其缺點也是非常明顯的,有些時候甚至是致命的。因為使用UDP協議來傳送數據,在數據發送后,在發送方并不確認對方是否接收到。這樣就可能導致傳送的數據在網絡中丟失,尤其在網絡條件并不很好的情況下,丟失數據包的現象就更多。所以傳送重要數據一般不采用UDP協議。
二.簡介VisualC#發送、接收UDP數據包使用的主要類及其用法:
用VisualC#實現UDP協議,最為常用,也是最為關鍵的類就是UdpClient,UdpClient位于命名空間System.Net.Sockets中,VisualC#發送、接收UDP數據包都是通過UdpClient類的。表01和表02是UdpClient類中常用方法和屬性及其簡要說明。
方法 |
說明 |
Close |
關閉 UDP 連接 |
Connect |
建立與遠程主機的連接 |
DropMulticastGroup |
退出多路廣播組 |
JoinMulticastGroup |
將 UdpClient 添加到多路廣播組 |
Receive |
返回已由遠程主機發送的 UDP 數據文報 |
Send |
將 UDP 數據文報發送到遠程主機 |
表01:UdpClient類中常用方法及其說明。
屬性 |
說明 |
Active |
獲取或設置一個值,該值指示是否已建立了與遠程主機的連接 |
Client |
獲取或設置基礎網絡套接字 |
表02:UdpClient類中常用方法及其說明。
1.Visual C#使用UdpClient類發送UDP數據包:
在具體使用中,一般分成二種情況:
(1). 知道遠程計算機IP地址:
"Send"方法的調用語法如下:
public int Send (
byte[] dgram ,
int bytes ,
IPEndPoint endPoint
) ; |
參數說明:
dgram 要發送的 UDP 數據文報(以字節數組表示)。
bytes 數據文報中的字節數。
endPoint 一個 IPEndPoint,它表示要將數據文報發送到的主機和端口。
返回值 已發送的字節數。
下面使用UdpClient發送UDP數據包的具體的調用例子:
IPAddress HostIP = new IPAddress.Parse ( "遠程計算機IP地址" ) ;
IPEndPoint host = new IPEndPoint ( HostIP , 8080 ) ;
UdpClient.Send ( "發送的字節" , "發送的字節長度" , host ) ; |
(2). 知道遠程計算機名稱::
知道遠程計算機名稱后,利用"Send"方法直接把UDP數據包發送到遠程主機的指定端口號上了,這種調用方式也是最容易的,語法如下:
public int Send (
byte[ ] dgram ,
int bytes ,
string hostname ,
int port
) ; |
參數說明:
dgram 要發送的 UDP 數據文報(以字節數組表示)。
bytes 數據文報中的字節數。
hostname 要連接到的遠程主機的名稱。
port 要與其通訊的遠程端口號。
返回值 已發送的字節數。
2.Visual C#使用UdpClient類接收UDP數據包:
接收UDP數據包使用的是UdpClient中的“Receive”方法。此方法的調用語法如下:
public byte [] Receive (
ref IPEndPoint remoteEP
) ; |
參數
remoteEP 是一個 IPEndPoint類的實例,它表示網絡中發送此數據包的節點。
如果指定了遠程計算機要發送到本地機的端口號,也可以通過偵聽本地端口號來實現對數據的獲取,下面就是通過偵聽本地端口號“8080”來獲取信息代碼:
server = new UdpClient ( ) ;
receivePoint = new IPEndPoint
(new IPAddress ( "127.0.0.1" ) , 8080 ) ;
byte[] recData = server.Receive ( ref receivePoint ) ; |
三.Visual C#實現UDP協議之網絡對時系統的體系結構及功能簡介:
在局域網中有很多應用軟件為了協同工作,需要保證客戶機上時間統一,而為了實現這一點,通常的做法是客戶機從一個時間相對正確的服務器讀取時間,以此來校正本地時間。如經??吹降腉PS對時系統等。本節編寫的局域網上對時系統的主要的功能是保證局域網上計算機時間、日期的統一。網絡對時程序是體系結構分成服務器端程序和客戶端程序二個部分,具體的作法是:在同一個網段上,固定一臺計算機作為對時的服務器,在這個網段的所有計算機都可以讀取這臺服務器上的時間和日期,并依此服務器上的時間和日期為基準,來確定本地的時間和日期。在服務器端程序需要達到以下功能:
能夠接收局域網中任一臺客戶機的請求
記錄請求客戶機的計算機名稱,和請求時間
準確發送服務器端的時間和日期
端程序要達到以下功能:
能夠設定服務器的主機或者IP地址
能夠接收服務器端發送的時間、日期信息
能夠以接收的服務器端時間、日期為基準,校正本地時間
因此在具體用Visual C#實現網絡對時系統時就包括二個部分:服務器端程序和客戶端程序。下面首先介紹Visual C#實現網絡對時系統中服務器端程序的具體步驟。
四.Visual C#實現網絡對時系統之服務器端程序的具體步驟:
服務器端程序比客戶端程序相對要簡單,主要因是服務器端程序的工作比較簡單,就
是接收客戶端的對時請求、發送服務器端的時間數據。而于客戶端不僅要傳送和接收數據,還要把服務器端的時間提取出來,并以此來修改本地計算機的時間、日期。下面是用Visual C#實現網絡對時系統之服務器端程序的具體步驟步驟。
1.啟動Visual Studio .Net。
2.選擇菜單【文件】|【新建】|【項目】后,彈出【新建項目】對話框。
3.將【項目類型】設置為【Visual C#項目】。
4.將【模板】設置為【Windows應用程序】。
5.在【名稱】文本框中輸入【UDP對時服務器端】。
6.在【位置】的文本框中輸入【E:\VS.NET項目】,然后單擊【確定】按鈕
7.在【解決方案資源管理器】窗口中,雙擊Form1.cs文件,進入Form1.cs文件的編輯界面。
8.在Form1.cs文件的開頭,用下列導入命名空間代碼替代系統缺省的導入命名空間代碼。
using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Net ;
using System.Net.Sockets ;
using System.Threading ;
//程序中使用到線程
using System.Text ;
//程序中使用到編碼 |
9.切換到【Form1.cs(設計)】窗口,并從【工具箱】中的【Windows窗體組件】中往窗體中拖入下列組件,并執行相應操作:
一個Label組件,顯示對時服務器正在運行信息
一個ListBox組件,名稱為listBox1,用以顯示客戶端和服務器端交流的日志
一個Button組件,名稱為button1,并在其拖入窗體后,雙擊,則系統會在Form1.cs文件中產生其Click事件對應的處理代碼。
10.在【解決方案資源管理器】窗口中,雙擊Form1.cs文件,進入Form1.cs文件的編輯界面。在Form1.cs中的class代碼區添加下列代碼,下列代碼是定義程序中使用的全局變量和創建全局使用的實例:
private UdpClient server ;
private IPEndPoint receivePoint ;
private int port = 8080 ;
//定義端口號
private int ip = 127001 ;
//設定本地IP地址
private Thread startServer ; |
11.以下面代碼替代系統產生的InitializeComponent過程。
private void InitializeComponent ( )
{
this.listBox1 = new System.Windows.Forms.ListBox ( ) ;
this.label1 = new System.Windows.Forms.Label ( ) ;
this.button1 = new System.Windows.Forms.Button ( ) ;
this.SuspendLayout ( ) ;
this.listBox1.ItemHeight = 12 ;
this.listBox1.Location = new System.Drawing.Point ( 14 , 40 ) ;
this.listBox1.Name = "listBox1" ;
this.listBox1.Size = new System.Drawing.Size ( 268 , 220 ) ;
this.listBox1.TabIndex = 0 ;
this.label1.ForeColor = System.Drawing.Color.Red ;
this.label1.Location = new System.Drawing.Point ( 44 , 10 ) ;
this.label1.Name = "label1" ;
this.label1.Size = new System.Drawing.Size ( 210 , 24 ) ;
this.label1.TabIndex = 1 ;
this.label1.Text = "UDP對時服務器端正在運行......" ;
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;
this.button1.Location = new System.Drawing.Point ( 106 , 278 ) ;
his.button1.Name = "button1" ;
this.button1.Size = new System.Drawing.Size ( 75 , 34 ) ;
this.button1.TabIndex = 2 ;
this.button1.Text = "清除信息" ;
this.button1.Click += new System.EventHandler ( this.button1_Click ) ;
this.AutoScaleBaseSize = new System.Drawing.Size ( 6 , 14 ) ;
this.ClientSize = new System.Drawing.Size ( 300 , 329 ) ;
this.Controls.AddRange ( new System.Windows.Forms.Control[] {
this.button1 ,
this.listBox1 ,
this.label1} ) ;
this.MaximizeBox = false ;
this.Name = "Form1" ;
this.Text = "UDP對時服務器端" ;
this.Load += new System.EventHandler ( this.Form1_Load ) ;
this.ResumeLayout ( false ) ;
} |
至此,【UDP對時服務器端】項目的界面設計和功能實現的前期工作就完成了,設計界面如圖01所示:

圖01:【UDP對時服務器端】項目的設計界面
12.在Form1.cs文件中的InitializeComponent過程的后面添加下面代碼,下列代碼是定義過程“start_server”。此過程的功能是獲取客戶端對時請求數據,并向客戶端發送服務器當前時間和日期。
public void start_server ( )
{
while ( true )
{
//接收從遠程主機發送到本地8080端口的數據
byte[] recData = server.Receive ( ref receivePoint ) ;
ASCIIEncoding encode = new ASCIIEncoding ( ) ;
//獲得客戶端請求數據
string Read_str = encode.GetString ( recData ) ;
//提取客戶端的信息,存放到定義為temp的字符串數組中
string[] temp = Read_str.Split ( "/".ToCharArray ( ) ) ;
//顯示端口號的請求信息
listBox1.Items.Add ( "時間:"+ DateTime.Now.
ToLongTimeString ( ) + " 接收信息如下:" ) ;
listBox1.Items.Add ( "客戶機:" + temp[0] ) ;
listBox1.Items.Add ( "端口號:" + temp[1] ) ;
//發送服務器端時間和日期
byte[] sendData =encode.GetBytes
( System.DateTime.Now.ToString ( ) ) ;
listBox1.Items.Add ( "發送服務器時間!" ) ;
//對遠程主機的指定端口號發送服務器時間
server.Send ( sendData , sendData.Length ,
temp[0] , Int32.Parse ( temp[1] ) ) ;
}
} |
請注意:上述代碼中約定客戶機程序發送對時請求信息到服務器的8080端口號。服務器端程序接收發送到本地8080端口號的數據就完成了數據接收。為了能夠讓服務器端程序知道是那臺客戶機提出請求和要把對時信息發送到客戶機的那個端口號上,客戶端程序對發送的對時請求信息進行了設計??蛻舳说膶r請求信息結構為:
計算機名稱 + / + 客戶機接收信息端口號
這樣如果客戶端計算機名稱為:majinhu,接收服務器端時間數據的端口號是8080,則客戶端程序發送的對時請求數據就為:majinhu/8080。
服務器端程序在接收到客戶端對時請求數據,并進行分析后,就能夠通過UdpClient類的Send方法準確的把服務器端當前的時間和日期發送到客戶端指定的端口號上。這樣客戶端程序通過讀取指定的端口號,就能夠獲得服務器端當前的時間和日期,從而以此來修正客戶端的時間和日期了。
13.在“start_server”過程之后面添加下面代碼,下列代碼是定義“run”過程?!皉un”過程的作用是創建一個線程實例,并以“start_server”過程來初始化線程實例。之所以采用線程是因為服務器端程序需要不間斷讀取發送到8080端口號,并且Receive方法是一個阻塞式方法。采用線程就是為了保證服務器端程序正常運行:
public void run ( )
{
//利用本地8080端口號來初始化一個UDP網絡服務
server = new UdpClient ( port ) ;
receivePoint = new IPEndPoint ( new IPAddress ( ip ) , port ) ;
//開一個線程
startServer = new Thread ( new ThreadStart ( start_server ) ) ;
//啟動線程
startServer.Start ( ) ;
} |
14.在Form1.cs中的Main函數之后添加下列代碼,下列代碼是定義“Form1_Load”事件,在此事件中將調用“run”過程,這樣當服務器端程序運行后,就啟動網絡對時服務:
private void Form1_Load ( object sender , System.EventArgs e )
{
//啟動對時服務
run ( ) ;
} |
15.在Form1.cs文件中的“Form1_Load”事件之后,添加下列代碼,下列代碼是定義button1的“Click”事件,此事件的作用是清除服務器端程序顯示的日志信息:
private void button1_Click ( object sender , System.EventArgs e )
{
//清除服務器端程序日志
listBox1.Items.Clear ( ) ;
} |
16.用下列代碼替換Form1.cs中的Dispose方法。下列代碼的功能是手動收集程序中使用的資源:
protected override void Dispose ( bool disposing )
{
try
{
//關閉線程
startServer.Abort ( ) ;
//清除資源
server.Close ( ) ;
}
catch
{
} ;
if ( disposing )
{
if ( components != null )
{
components.Dispose ( ) ;
}
}
base.Dispose ( disposing ) ;
} |
至此,在上述步驟都正確完成,【UDP對時服務器端】項目的全部工作就完成了。圖02【UDP對時服務器端】運行后的界面,在日志信息中記錄了對時請求客戶機的名稱,發送對時數據的端口號以及客戶端請求的時間:

圖02:【UDP對時服務器端】項目的運行界面
原文轉自:http://www.kjueaiud.com
老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月
|