12.并以下面代碼替換Form.cs中由系統產生的InitializeComponent過程。
PRivate void InitializeComponent ( ){this.button1 = new System.Windows.Forms.Button ( ) ;this.button2 = new System.Windows.Forms.Button ( ) ;this.textBox1 = new System.Windows.Forms.TextBox ( ) ;this.textBox2 = new System.Windows.Forms.TextBox ( ) ;this.label1 = new System.Windows.Forms.Label ( ) ;this.label2 = new System.Windows.Forms.Label ( ) ;this.label3 = new System.Windows.Forms.Label ( ) ;this.textBox3 = new System.Windows.Forms.TextBox ( ) ;this.SuspendLayout ( ) ;this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;this.button1.Location = new System.Drawing.Point ( 128 , 128 ) ;this.button1.Name = "button1" ;this.button1.Size = new System.Drawing.Size ( 112 , 40 ) ;this.button1.TabIndex = 0 ;this.button1.Text = "獲取" ;this.button1.Click += new System.EventHandler ( this.button1_Click ) ;this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;this.button2.Location = new System.Drawing.Point ( 128 , 184 ) ;this.button2.Name = "button2" ;this.button2.Size = new System.Drawing.Size ( 112 , 40 ) ;this.button2.TabIndex = 1 ;this.button2.Text = "對時" ;this.button2.Click += new System.EventHandler ( this.button2_Click ) ;this.textBox1.Location = new System.Drawing.Point ( 120 , 56 ) ;this.textBox1.Name = "textBox1" ;this.textBox1.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox1.TabIndex = 2 ;this.textBox1.Text = "" ;this.textBox2.Location = new System.Drawing.Point ( 120 , 88 ) ;this.textBox2.Name = "textBox2" ;this.textBox2.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox2.TabIndex = 3 ;this.textBox2.Text = "" ;this.label1.Location = new System.Drawing.Point ( 48 , 56 ) ;this.label1.Name = "label1" ;this.label1.TabIndex = 4 ;this.label1.Text = "本地時間:" ;this.label2.Location = new System.Drawing.Point ( 40 , 88 ) ;this.label2.Name = "label2" ;this.label2.Size = new System.Drawing.Size ( 88 , 24 ) ;this.label2.TabIndex = 5 ;this.label2.Text = "服務器時間:" ;this.label3.Location = new System.Drawing.Point ( 16 , 24 ) ;this.label3.Name = "label3" ;this.label3.Size = new System.Drawing.Size ( 112 , 23 ) ;this.label3.TabIndex = 6 ;this.label3.Text = "設定服務器地址:" ;this.textBox3.Location = new System.Drawing.Point ( 120 , 24 ) ;this.textBox3.Name = "textBox3" ;this.textBox3.Size = new System.Drawing.Size ( 200 , 21 ) ;this.textBox3.TabIndex = 7 ;this.textBox3.Text = "" ;this.AutoScaleBaseSize = new System.Drawing.Size ( 6 , 14 ) ;this.ClientSize = new System.Drawing.Size ( 352 , 245 ) ;this.Controls.AddRange ( new System.Windows.Forms.Control[] { this.textBox3 , this.textBox2 , this.textBox1 , this.button2 , this.button1 , this.label1 , this.label2 , this.label3} ) ;this.MaximizeBox = false ;this.Name = "Form1" ;this.Text = "UDP對時客戶端" ;this.ResumeLayout ( false ) ;}
至此【UDP對時客戶端】項目的界面設計和程序功能實現的前期工作就基本完成了,其設計界面如圖03所示:

圖03:【UDP對時客戶端】項目的設計界面
13.在Form1.cs中的InitializeComponent過程之后,添加下列代碼,下列代碼的功能是在程序中導入WinAPI函數——SetSystemTime,這個函數位于文件Kernel32.dll。程序就是通過此函數來更正系統時間的。
[ DllImport ( "Kernel32.dll" )]private static extern bool SetSystemTime ( SystemTime time ) ;//引入API函數
14.并把它添加到在導入WinAPI函數代碼之后,再添加下列代碼,下列代碼是定義“start_client”過程。此過程的功能是向服務器端傳送對時請求,并獲取從服務器端反饋來的時間日期數據。
{ client = new UdpClient ( port ) ; ipAddress a = IPAddress.Parse ( "127001" ) ; receivePoint = new IPEndPoint ( a , port ) ; IPAddress HostIP ; bool continueLoop = true ; while ( continueLoop ) { string hostName = Dns.GetHostName ( ) ; System.Text.ASCIIEncoding encode = new System.Text.ASCIIEncoding ( ) ; //定義發送到服務器端的請求信息 //請求信息是一個字符串,為客戶端名稱和接收服務器反饋信息的端口號組成的字符串 string sendString = hostName + "/" + port.ToString ( ) ; byte[] sendData = encode.GetBytes ( sendString ) ; //判定使用者輸入的是IP地址還是計算機名稱 try { HostIP = IPAddress.Parse ( textBox3.Text ) ; } catch { //假如輸入的是計算機名稱,則按照執行下列代碼。 //發送請求信息 client.Send ( sendData , sendData. Length , textBox3.Text , 8080 ) ; //接收來自服務器端的信息 byte[] recData = client.Receive ( ref receivePoint ) ; timeString = encode.GetString ( recData ) ; client.Close ( ) ; continueLoop=false ; return ; } //輸入的是IP地址,則執行下列代碼 IPEndPoint host = new IPEndPoint ( HostIP ,8080 ) ; //發送請求信息 client.Send ( sendData , sendData.Length , host ) ; //接收來自服務器端的信息 byte[] recData1 = client.Receive ( ref receivePoint ) ; //獲取服務器端的時間和日期 timeString = encode.GetString ( recData1 ) ; client.Close ( ) ; //退出循環 continueLoop=false ; }}
假如“start_client”過程正確調用,就把服務器端的時間和日期保存到timeString字符串中了。
17.用下列代碼替換Form1.cs中button1的“Click”事件的處理代碼。下列代碼的功能是調用“start_client”過程,獲取并顯示服務器端程序的時間和日期信息。
private void button1_Click ( object sender , System.EventArgs e ){ start_client ( ) ; textBox1.Text = DateTime.Now.ToString ( ) ; //顯示客戶端當前時間和日期 textBox2.Text = timeString ; //顯示服務器當前時間和日期}
18.用下列代碼替換Form1.cs中button2的“Click”事件對應的處理代碼。下列代碼的功能是根據獲取的服務器時間和日期數據來更正客戶端時間和日期。
private void button2_Click ( object sender , System.EventArgs e ){ start_client ( ) ; //把接收來的數據轉換時間日期格式 try { temp = DateTime.Parse ( timeString ) ; } catch { MessageBox.Show ( "錯誤時間" ) ; return ; } //根據得到的時間日期,來定義時間、日期 SystemTime st= new SystemTime ( ) ; st.year= ( short )temp.Year ; st.Month= ( short )temp.Month ; st.DayOfWeek= ( short )temp.DayOfWeek ; st.Day= ( short )temp.Day ; st.Hour=Convert.ToInt16 ( temp.Hour ) ; if ( st.Hour>=12 ) { st.Hour-= ( short )8 ; } else if ( st.Hour >= 8 ) { st.Hour-= ( short )8 ; } else { st.Hour+= ( short )16 ; } st.Minute=Convert.ToInt16 ( temp.Minute ) ; st.Second=Convert.ToInt16 ( temp.Second ) ; st.Milliseconds=Convert.ToInt16 ( temp.Millisecond ) ; //修改本地端的時間和日期 if ( SetSystemTime ( st ) ) { MessageBox.Show ( DateTime.Now.ToString ( ) ,"修改成功" ) ; } else MessageBox.Show ( "不成功!" ,"不成功" ) ;}
至此,在正確完成上述步驟,全部保存后,【網絡對時客戶端】項目的全部工作就完成了。
六.運行基于UDP協議網絡對時系統,實現網絡對時:
首先要確認確認網絡對時系統中的服務器端程序已經運行和其IP地址或主機名。然后在客戶機上運行網絡對時系統中的客戶端程序,在正確輸入運行網絡對時系統服務器端程序對應的主機名或者IP地址后,單擊客戶端程序中【獲取】按鈕,則在程序的文本框中顯示服務器當前時間和日期和客戶端當前的時間和日期。若發現二種存在差異,單擊【對時】按鈕,則將以服務器當前時間和日期來修正客戶機的時間和日期。修改成功則彈出【修改成功】提示框,反之則彈出【不成功】提示框,圖04是【UDP對時客戶端】項目根據服務器端當前時間和日期信息成功更改本地時間和日期后的界面:

圖04:【UDP對時客戶端】項目的運行界面
七.總結:
本文具體介紹了UDP協議,.Net FrameWork SDK提供給Visual C#用以操作UDP協議的主要類庫,以及通過一個具體而使用的示例——實現一個網絡對時系統,介紹在Visual C#實現UDP協議的具體方法和過程。UDP由于其自身的缺點注定在某些領域無法利用它,但在可以利用它的領域,UDP以其快捷、簡單、實用的特點正在受到更多程序員的歡迎。尤其在現代,網絡運行態勢越來越好的情況下,可以預見的是UDP在網絡中的應用情景將更廣闊。希望本文的內容對您把握用Visual C#編寫基于UDP的網絡應用程序有所幫助。