Visual C#託管Socket的實現方法(轉載的他人的文章,好好收藏吧!)

 shades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gifshades_smile.gif
Visual C#託管Socket的實現方法(一) (1)
作者:王天 發文時間:2003.11.19    
    
Socket就是套接字,它是網絡編程中最常用遇到的概念和工具。在TCP/IP網絡中,傳送和接收數據就會經常使用到Socket,由於使用Socket能夠在網絡上處理複雜數據,所以在各種網絡應用程序中,涉及到數據傳送和接收,一般都會使用Socket,可見要掌握網絡編程,精通Socket是非常重要。由於Socket本身的複雜性,決定了掌握它是比較困難的。Visual C#是微軟公司推薦的開發.Net平臺應用程序的主要語言,隨着.Net的深入人心,目前很多有遠見的公司都把以前的軟件轉向了.Net平臺。掌握網絡編程始終是學習一種開發語言的重點,這一點對於Visual C#也同樣如此。Visual C#實現網絡功能其關鍵也是掌握託管Socket的使用方法。本文就來詳細介紹Visual C#中利用託管Socket實現網絡數據傳送和接收的實現方法及其注意事項。 

 一.Visual C#中操作Socket:

雖然Visual C#可以使用NetworkStream來傳送、接收數據,但NetworkStream在使用中有很大的侷限性,利用NetworkStream只能傳送和接收字符類型的數據,如果要傳送的是一些複雜的數據如:二進制數據等,它就顯得能力有限了。但使用NetworkStream在處理自身可操作數據時,的確要比Socket方便許多。Socket(套接字)幾乎可以處理任何在網絡中需要傳輸的數據類型。

我們知道Visual C#和Visual C++的區別之一,就是Visual C#沒有屬於自己的類庫,而Visual C++卻是有的,Visual C#使用的類庫是.Net框架爲所有開發.Net平臺程序語言提供的一個公用的類庫——.Net FrameWork SDK。Visual C#主要網絡功能主要使用.Net FrameWork SDK中的提供的二個命名空間“System.Net.Sockets”和“System.Net”。而實現Socket使用的是命名空間“System.Net.Sockets”中的Socket類。Visual C#通過創建Socket類的實例來實現Socket的託管版本。在Visual C#中創建完Socket實例後,可以通過此Socket實例的Bind方法綁定到網絡中指定的終結點,也可以通過其Connect方法向指定的終結點建立的連接。連接創建完畢,就可以使用其Send或SendTo方法將數據發送到Socket;同樣使用其的Receive或ReceiveFrom方法從Socket中讀取數據。在Socket使用完畢後,請使用其的Shutdown方法禁用Socket,並使用Close方法關閉Socket。表01和表02是Socket類中的常用屬性和方法及其簡要說明。


屬性
說明

AddressFamily
獲取Socket的地址族。

Available
獲取已經從網絡接收且可供讀取的數據量。

Blocking
獲取或設置一個值,該值指示Socket是否處於阻塞模式。

Connected
獲取一個值,該值指示Socket是否已連接到遠程資源。

Handle
獲取Socket的操作系統句柄。

LocalEndPoint
獲取本地終結點。

ProtocolType
獲取Socket的協議類型。

RemoteEndPoint
獲取遠程終結點。

SocketType
獲取Socket的類型。

 

表01:Socket類的常用屬性及其說明


方法
說明

Accept
創建新的Socket以處理傳入的連接請求。

BeginAccept
開始一個異步請求,以創建新的Socket來接受傳入的連接請求。

BeginConnect
開始對網絡設備連接的異步請求。

BeginReceive
開始從連接的Socket中異步接收數據。

BeginReceiveFrom
開始從指定網絡設備中異步接收數據。

BeginSend
將數據異步發送到連接的

BeginSendTo
向特定遠程主機異步發送數據。

Bind
使Socket與一個本地終結點相關聯。

Close
強制Socket連接關閉。

Connect
建立到遠程設備的連接。

EndAccept
結束異步請求以創建新的Socket來接受傳入的連接請求

EndConnect
結束掛起的異步連接請求。

EndReceive
結束掛起的異步讀取。

EndReceiveFrom
結束掛起的、從特定終結點進行異步讀取。

EndSend
結束掛起的異步發送

EndSendTo
結束掛起的、向指定位置進行的異步發送。

GetSocketOption
返回Socket選項的值。

IOControl
爲Socket設置低級別操作模式

Listen
將Socket置於偵聽狀態。

Poll


Receive
接收來自連接Socket的數據。

ReceiveFrom
接收數據文報並存儲源終結點。

Select
確定一個或多個套接字的狀態。

Send
將數據發送到連接的

SendTo
將數據發送到特定終結點。

SetSocketOption
設置Socket選項。

Shutdown
禁用某Socket上的發送和接收。

 

表02:Socket類的常用方法及其說明

其中“BeginAccept”和“EndAccept”、“BeginConnect”和“EndConnect”、

“BeginReceive”和“EndReceive”、“BeginReceiveFrom”和“EndReceiveFrom”、

“BeginSend”和“EndSend”、“BeginSendTo”和“EndSendTo”是六組異步方法,

其功能分別相當於“Accept”、“Connect”、“Receive”、“ReceiveFrom”、

“Send”和“SendTo”方法。

下面就通過一個具體的示例,來介紹Visual C#中如何通過託管Socket實現數據傳送和接收的具體方法。

本文示例其實是由二部分組成,也可以看成是客戶機程序和服務器程序。客戶機程序功能是通過

Socket向服務器程序創建連接,並在連接完成後,向服務器發送數據;服務器程序通過偵聽端口,接受網絡的Socket的連接請求,並在連接完成後,接收從客戶機發送來的數據,並顯示出來。下面首先來介紹Visual C#通過託管Socket實現客戶機程序的具體方法。

tongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.giftongue_smile.gif  
Visual C#託管Socket的實現方法(一) (2)    
作者:王天 發文時間:2003.11.19    
    
二.本文介紹程序的設計、調試、運行的軟件環境:

(1).微軟公司視窗2000服務器版

(2).Visual Studio .Net正式版,.Net FrameWork SDK版本號3705

四.利用Socket來傳送數據:

Visual C#在使用Socket傳送數據時要注意下列問題的解決方法:

1.創建Socket實例,使用此實例創建和遠程終結點的連接,並判斷連接是否成功建立。

2.發送數據到Socket,實現數據傳送。

這些問題解決方法都可以在下面介紹代碼中找到相對應的部分。由於下面的代碼都有詳細的註解,

這裏就不詳細介紹。下面是利用Socket傳送數據的具體實現步驟:

1.啓動Visual Studio .Net,並新建一個Visual C#項目,

項目名稱爲【利用Socket來發送數據】。

2.把Visual Studio .Net的當前窗口切換到【Form1.cs(設計)】窗口,

並從【工具箱】中的【Windows窗體組件】選項卡中往Form1窗體中拖入下列組件,並執行相應操作:

二個TextBox組件,一個用以輸入遠程主機的IP地址,一個用以輸入往遠程主機傳送的數據。

一個StausBar組件,用以顯示程序的運行狀況。

一個ListBox組件,用以顯示程序已傳送的數據信息。

三個Label組件。

二個Button組件,名稱分別爲button1、button2,並在這二個組件被拖入窗體後,分別雙擊它們,則系統會在Form1.cs文件中自動產生這二個組件的Click事件對應的處理代碼。

3.【解決方案資源管理器】窗口中,雙擊Form1.cs文件,進入Form1.cs文件的編輯界面。

4.以下面代碼替代系統產生的InitializeComponent過程:


private void InitializeComponent ( )
{
 this.label1 = new System.Windows.Forms.Label ( ) ;
 this.textBox1 = new System.Windows.Forms.TextBox ( ) ;
 this.button1 = new System.Windows.Forms.Button ( ) ;
 this.label2 = new System.Windows.Forms.Label ( ) ;
 this.textBox2 = new System.Windows.Forms.TextBox ( ) ;
 this.listBox1 = new System.Windows.Forms.ListBox ( ) ;
 this.statusBar1 = new System.Windows.Forms.StatusBar ( ) ;
 this.label3 = new System.Windows.Forms.Label ( ) ;
 this.button2 = new System.Windows.Forms.Button ( ) ;
 this.SuspendLayout ( ) ;
 this.label1.Location = new System.Drawing.Point ( 24 , 20 ) ;
 this.label1.Name = "label1" ;
 this.label1.Size = new System.Drawing.Size ( 74 , 30 ) ;
 this.label1.TabIndex = 0 ;
 this.label1.Text = "IP地址:" ;
 this.textBox1.BorderStyle = System.Windows.
         Forms.BorderStyle.FixedSingle ;
 this.textBox1.Location = new System.Drawing.Point ( 94 , 18 ) ;
 this.textBox1.Name = "textBox1" ;
 this.textBox1.Size = new System.Drawing.Size ( 166 , 21 ) ;
 this.textBox1.TabIndex = 1 ;
 this.textBox1.Text = "" ;
 this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;
 this.button1.Location = new System.Drawing.Point ( 280 , 14 ) ;
 this.button1.Name = "button1" ;
 this.button1.Size = new System.Drawing.Size ( 62 , 28 ) ;
 this.button1.TabIndex = 2 ;
 this.button1.Text = "連接" ;
 this.button1.Click += new System.EventHandler ( this.button1_Click ) ;
 this.label2.Location = new System.Drawing.Point ( 16 , 64 ) ;
 this.label2.Name = "label2" ;
 this.label2.TabIndex = 3 ;
 this.label2.Text = "發送信息:" ;
 this.textBox2.BorderStyle = System.Windows.
         Forms.BorderStyle.FixedSingle ;
 this.textBox2.Location = new System.Drawing.Point ( 94 , 58 ) ;
 this.textBox2.Name = "textBox2" ;
 this.textBox2.Size = new System.Drawing.Size ( 166 , 21 ) ;
 this.textBox2.TabIndex = 4 ;
 this.textBox2.Text = "" ;
 this.listBox1.ItemHeight = 12 ;
 this.listBox1.Location = new System.Drawing.Point ( 20 , 118 ) ;
 this.listBox1.Name = "listBox1" ;
 this.listBox1.Size = new System.Drawing.Size ( 336 , 160 ) ;
 this.listBox1.TabIndex = 6 ;
 this.statusBar1.Location = new System.Drawing.Point ( 0 , 295 ) ;
 this.statusBar1.Name = "statusBar1" ;
 this.statusBar1.Size = new System.Drawing.Size ( 370 , 22 ) ;
 this.statusBar1.TabIndex = 7 ;
 this.statusBar1.Text = "無連接" ;
 this.label3.Location = new System.Drawing.Point ( 14 , 94 ) ;
 this.label3.Name = "label3" ;
 this.label3.Size = new System.Drawing.Size ( 128 , 23 ) ;
 this.label3.TabIndex = 8 ;
 this.label3.Text = "已經發送的信息:" ;
 this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat ;
 this.button2.Location = new System.Drawing.Point ( 280 , 54 ) ;
 this.button2.Name = "button2" ;
 this.button2.Size = new System.Drawing.Size ( 62 , 28 ) ;
 this.button2.TabIndex = 9 ;
 this.button2.Text = "發送" ;
 this.button2.Click += new System.EventHandler
         ( this.button2_Click ) ;
 this.AutoScaleBaseSize = new System.Drawing.Size ( 6 , 14 ) ;
 this.ClientSize = new System.Drawing.Size ( 370 , 317 ) ;
 this.Controls.AddRange ( new System.Windows.Forms.Control[] {
    this.button2 ,
    this.statusBar1 ,
    this.listBox1 ,
    this.textBox2 ,
    this.label2 ,
    this.button1 ,
    this.textBox1 ,
    this.label1 ,
    this.label3} ) ;
 this.FormBorderStyle = System.
         Windows.Forms.FormBorderStyle.FixedSingle ;
 this.MaximizeBox = false ;
 this.Name = "Form1" ;
 this.Text = "利用Socket來發送數據" ;
 this.ResumeLayout ( false ) ;
}

 

至此【利用Sokcet來傳送數據】項目設計後的界面就完成了,具體如圖01所示:
 

圖01:【利用Sokcet來傳送數據】項目的設計界面


5.在Form1.cs文件的開頭的導入命名空間的代碼區,添加下列代碼,

下列代碼是導入下面程序中使用到的類所在的命名空間:


using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Net.Sockets ;
//使用到TcpListen類
using System.Net ;


72_72.gif72_72.gif72_72.gif72_72.gif72_72.gif72_72.gif72_72.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gifthumbs_up.gif
Visual C#託管Socket的實現方法(一) (3)    
作者:王天 發文時間:2003.11.19   
    
6.在Form1的class代碼區中加入下列代碼,下列代碼的作用是定義全局變量和創建全局使用的實例:


int port = 8000 ;
//定義偵聽端口號
private TcpClient tcpc  ;
//對服務器端創建TCP連接
private Socket stSend ; 
//創建發送數據套接字
private bool tcpConnect = false ;
//定義標識符,用以表示TCP連接是否建立

 

7.用下列代碼替換Form1.cs中的button1組件的Click事件對應的處理代碼,下列代碼的功能是初始化以創建的Socket實例,並向遠程終結點提出連接申請,並判斷連接是否建立:


private void button1_Click
( object sender , System.EventArgs e )
{
 //以下代碼是判斷是否和遠程終結點成功連接
 try
 {
  stSend = new Socket ( AddressFamily.InterNetwork ,
                  SocketType.Stream , ProtocolType.Tcp ) ;
  //初始化一個Socket實例
  IPEndPoint tempRemoteIP = new IPEndPoint
                  ( IPAddress.Parse ( textBox1.Text ) , port ) ;
  //根據IP地址和端口號創建遠程終結點
  EndPoint epTemp =  ( EndPoint ) tempRemoteIP ;
  stSend.Connect ( epTemp ) ;
  //連接遠程主機的8000端口號
  statusBar1.Text = "成功連接遠程計算機!" ;
  tcpConnect = true ;
  button1.Enabled = false  ;
  button2.Enabled = true  ;
 }
 catch ( Exception )
 {
  statusBar1.Text = "目標計算機拒絕連接請求!" ;
 } 
}

 

8.用下列代碼替換Form1.cs中button2組件的Click事件對應的處理代碼,下列代碼的功能是通過已建立的連接,利用Socket來傳送數據到遠程主機。


private void button2_Click
( object sender , System.EventArgs e )
{
 int iLength = textBox2.Text.Length ;
 //獲取要發送的數據的長度
 Byte [ ] bySend = new byte [ iLength ] ;
 //根據獲取的長度定義一個Byte類型數組
 bySend = System.Text.Encoding.Default.GetBytes
         ( textBox2.Text  ) ;
 //按照指定編碼類型把字符串指定到指定的Byte數組
 int i = stSend.Send  ( bySend ) ;
 //發送數據
 listBox1.Items.Add  ( textBox2.Text  ) ;
}

 

9.用下列代碼替換Form1.cs中“清理所有正在使用的資源。”對應的代碼。其作用是在程序退出之前,判斷連接狀態,如果沒有退出,則向遠程主機發送控制碼“STOP”,用以斷開和遠程主機的連接,並清除相應資源。所謂控制碼就是網絡應用程序之間彼此交換信息的一種自定義碼子,應用程序通過接收、發送這些碼子,可以明確網絡應用程序的行爲,保證執行的一致性,也就少了很多出錯的機率。控制碼在編寫遠程控制方面的應用程序時使用比較多。之所以要有這一步是因爲在用Visual C#編寫網絡應用程序的時候,很多人都遇到這樣的情況。當程序退出後,通過Windows的“資源管理器”看到的是進程數目並沒有減少。這是因爲程序中使用的線程可能並沒有有效退出。雖然Thread類中提供了“Abort”方法用以中止進程,但並不能夠保證成功退出。因爲進程中使用的某些資源並沒有回收。可見在某些情況下,依靠Visual C#的垃圾回收器也不能保證完全的回收資源,這時就需要我們自己手動回收資源的。下面就是手動回收資源採用的一種方法:


protected override void Dispose (  bool disposing  )
{
 if  (  tcpConnect  )
 {
  Byte [ ] bySend = new byte [ 4 ] ;
  //根據字符串“STOP”長度來定義Byte數組
  bySend = System.Text.Encoding.
                  Default.GetBytes ( "STOP" ) ;
  int i = stSend.Send  ( bySend ) ;
  //發送控制碼
  stSend.Close ( ) ;
  //關閉套接字
 }
 if (  disposing  )
 {
  if  ( components != null )
  {
   components.Dispose ( ) ;
  }
 }
 base.Dispose (  disposing  ) ;
}

 

至此在上述步驟都正確執行後,【利用Socket來傳送數據】就全部完成了。 

發佈了7 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章