靈魂-放水

          為學日益,為道日損。

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            296 Posts :: 10 Stories :: 274 Comments :: 0 Trackbacks

          ??????C#網絡編程我們知道C#和C++的差異之一,就是他本身沒有類庫,所使用的類庫是.Net框架中的類庫--.Net FrameWork SDK。在.Net FrameWork SDK中為網絡編程提供了二個名稱空間:"System.Net"和"System.Net.Sockets"。C#就是通過這二個名稱空間中封裝的類和方法實現網絡通訊的。

            首先我們解釋一下在網絡編程時候,經常遇到的幾個概念:同步(synchronous)、異步(asynchronous)、阻塞(Block)和非阻塞(Unblock):

            所謂同步方式,就是發送方發送數據包以后,不等接受方響應,就接著發送下一個數據包。異步方式就是當發送方發送一個數據包以后,一直等到接受方響應后,才接著發送下一個數據包。而阻塞套接字是指執行此套接字的網絡調用時,直到調用成功才返回,否則此套節字就一直阻塞在網絡調用上,比如調用StreamReader 類的Readlin ( )方法讀取網絡緩沖區中的數據,如果調用的時候沒有數據到達,那么此Readlin ( )方法將一直掛在調用上,直到讀到一些數據,此函數調用才返回;而非阻塞套接字是指在執行此套接字的網絡調用時,不管是否執行成功,都立即返回。同樣調用StreamReader 類的Readlin ( )方法讀取網絡緩沖區中數據,不管是否讀到數據都立即返回,而不會一直掛在此函數調用上。在Windows網絡通信軟件開發中,最為常用的方法就是異步非阻塞套接字。平常所說的C/S(客戶端/服務器)結構的軟件采用的方式就是異步非阻塞模式的。

            其實在用C#進行網絡編程中,我們并不需要了解什么同步、異步、阻塞和非阻塞的原理和工作機制,因為在.Net FrameWrok SDK中已經已經把這些機制給封裝好了。下面我們就用C#開一個具體的網絡程序來說明一下問題。

          一.本文中介紹的程序設計及運行環境

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

              (2)..Net Framework SDK Beta 2以上版本

          二.服務器端程序設計的關鍵步驟以及解決辦法:

             在下面接受的程序中,我們采用的是異步阻塞的方式。

             (1).首先要要在給定的端口上面創建一個"tcpListener"對象偵聽網絡上面的請求。當接收到連結請求后通過調用"tcpListener"對象的"AcceptSocket"方法產生一個用于處理接入連接請求的Socket的實例。下面是具體實現代碼:

          //創建一個tcpListener對象,此對象主要是對給定端口進行偵聽
          tcpListener = new TcpListener ( 1234 ) ;
          //開始偵聽
          tcpListener.Start ( ) ;
          //返回可以用以處理連接的Socket實例
          socketForClient = tcpListener.AcceptSocket ( ) ;
             (2).接受和發送客戶端數據:

             此時Socket實例已經產生,如果網絡上有請求,在請求通過以后,Socket實例構造一個"NetworkStream"對象,"NetworkStream"對象為網絡訪問提供了基礎數據流。我們通過名稱空間"System.IO"中封裝的二個類"StreamReader"和"StreamWriter"來實現對"NetworkStream"對象的訪問。其中"StreamReader"類中的ReadLine ( )方法就是從"NetworkStream"對象中讀取一行字符;"StreamWriter"類中的WriteLine ( )方法就是對"NetworkStream"對象中寫入一行字符串。從而實現在網絡上面傳輸字符串,下面是具體的實現代碼:

          try
          {
          //如果返回值是"true",則產生的套節字已經接受來自遠方的連接請求
          if ( socketForClient.Connected )
          {
          ListBox1.Items.Add ( "已經和客戶端成功連接!" ) ;
          while ( true )
          {
          //創建networkStream對象通過網絡套節字來接受和發送數據
          networkStream = new NetworkStream ( socketForClient ) ;
          //從當前數據流中讀取一行字符,返回值是字符串
          streamReader = new StreamReader ( networkStream ) ;
          string msg = streamReader.ReadLine ( ) ;
          ListBox1.Items.Add ( "收到客戶端信息:" + msg ) ;
          streamWriter = new StreamWriter ( networkStream ) ;
          if ( textBox1.Text != "" )
          {
          ListBox1.Items.Add ( "往客戶端反饋信息:" + textBox1.Text ) ;
          //往當前的數據流中寫入一行字符串
          streamWriter.WriteLine ( textBox1.Text ) ;
          //刷新當前數據流中的數據
          streamWriter.Flush ( ) ;
          }
          }
          }
          }
          catch ( Exception ey )
          {
          MessageBox.Show ( ey.ToString ( ) ) ;
          }

             (3).最后別忘了要關閉所以流,停止偵聽網絡,關閉套節字,具體如下:

          //關閉線程和流
          networkStream.Close ( ) ;
          streamReader.Close ( ) ;
          streamWriter.Close ( ) ;
          _thread1.Abort ( ) ;
          tcpListener.Stop ( ) ;
          socketForClient.Shutdown ( SocketShutdown.Both ) ;
          socketForClient.Close ( ) ;
          三.C#網絡編程服務器端程序的部分源代碼(server.cs) :

             由于在此次程序中我們采用的結構是異步阻塞方式,所以在實際的程序中,為了不影響服務器端程序的運行速度,我們在程序中設計了一個線程,使得對網絡請求偵聽,接受和發送數據都在線程中處理,請在下面的代碼中注意這一點,下面是server.cs的完整代碼:

          using System ;
          using System.Drawing ;
          using System.Collections ;
          using System.ComponentModel ;
          using System.Windows.Forms ;
          using System.Data ;

          using System.Net.Sockets ;
          using System.IO ;
          using System.Threading ;
          using System.Net ;
          //導入程序中使用到的名字空間
          public class Form1 : Form
          {
          private ListBox ListBox1 ;
          private Button button2 ;
          private Label label1 ;
          private TextBox textBox1 ;
          private Button button1 ;
          private Socket socketForClient ;
          private NetworkStream networkStream ;
          private TcpListener tcpListener ;
          private StreamWriter streamWriter ;
          private StreamReader streamReader ;
          private Thread _thread1 ;
          private System.ComponentModel.Container components = null ;
          public Form1 ( )
          {
          InitializeComponent ( ) ;
          }
          //清除程序中使用的各種資源
          protected override void Dispose ( bool disposing )
          {
          if ( disposing )
          {
          if ( components != null )
          {
          components.Dispose ( ) ;
          }
          }
          base.Dispose ( disposing ) ;
          }
          private void InitializeComponent ( )
          {
          label1 = new Label ( ) ;
          button2 = new Button ( ) ;
          button1 = new Button ( ) ;
          ListBox1 = new ListBox ( ) ;
          textBox1 = new TextBox ( ) ;
          SuspendLayout ( ) ;
          label1.Location = new Point ( 8 , 168 ) ;
          label1.Name = "label1" ;
          label1.Size = new Size ( 120 , 23 ) ;
          label1.TabIndex = 3 ;
          label1.Text = "往客戶端反饋信息:" ;
          //同樣的方式設置其他控件,這里略去

          this.Controls.Add ( button1 ) ;
          this.Controls.Add ( textBox1 ) ;
          this.Controls.Add ( label1 ) ;
          this.Controls.Add ( button2 ) ;
          this.Controls.Add ( ListBox1 ) ;
          this.MaximizeBox = false ;
          this.MinimizeBox = false ;
          this.Name = "Form1" ;
          this.Text = "C#的網絡編程服務器端!" ;
          this.Closed += new System.EventHandler ( this.Form1_Closed ) ;
          this.ResumeLayout ( false ) ;

          }
          private void Listen ( )
          {
          //創建一個tcpListener對象,此對象主要是對給定端口進行偵聽
          tcpListener = new TcpListener ( 1234 ) ;
          //開始偵聽
          tcpListener.Start ( ) ;
          //返回可以用以處理連接的Socket實例
          socketForClient = tcpListener.AcceptSocket ( ) ;
          try
          {
          //如果返回值是"true",則產生的套節字已經接受來自遠方的連接請求
          if ( socketForClient.Connected )
          {
          ListBox1.Items.Add ( "已經和客戶端成功連接!" ) ;
          while ( true )
          {
          //創建networkStream對象通過網絡套節字來接受和發送數據
          networkStream = new NetworkStream ( socketForClient ) ;
          //從當前數據流中讀取一行字符,返回值是字符串
          streamReader = new StreamReader ( networkStream ) ;
          string msg = streamReader.ReadLine ( ) ;
          ListBox1.Items.Add ( "收到客戶端信息:" + msg ) ;
          streamWriter = new StreamWriter ( networkStream ) ;
          if ( textBox1.Text != "" )
          {
          ListBox1.Items.Add ( "往客戶端反饋信息:" + textBox1.Text ) ;
          //往當前的數據流中寫入一行字符串
          streamWriter.WriteLine ( textBox1.Text ) ;
          //刷新當前數據流中的數據
          streamWriter.Flush ( ) ;
          }
          }
          }
          }
          catch ( Exception ey )
          {
          MessageBox.Show ( ey.ToString ( ) ) ;
          }
          }
          static void Main ( )
          {
          Application.Run ( new Form1 ( ) ) ;

          }

          private void button1_Click ( object sender , System.EventArgs e )
          {
          ListBox1.Items .Add ( "服務已經啟動!" ) ;
          _thread1 = new Thread ( new ThreadStart ( Listen ) ) ;
          _thread1.Start ( ) ;

          }

          private void button2_Click ( object sender , System.EventArgs e )
          {
          //關閉線程和流
          networkStream.Close ( ) ;
          streamReader.Close ( ) ;
          streamWriter.Close ( ) ;
          _thread1.Abort ( ) ;
          tcpListener.Stop ( ) ;
          socketForClient.Shutdown ( SocketShutdown.Both ) ;
          socketForClient.Close ( ) ;
          }
          private void Form1_Closed ( object sender , System.EventArgs e )
          {
          //關閉線程和流
          networkStream.Close ( ) ;
          streamReader.Close ( ) ;
          streamWriter.Close ( ) ;
          _thread1.Abort ( ) ;
          tcpListener.Stop ( ) ;
          socketForClient.Shutdown ( SocketShutdown.Both ) ;
          socketForClient.Close ( ) ;
          }
          }



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=622873

          posted on 2006-09-24 11:17 放水老倌 閱讀(337) 評論(0)  編輯  收藏 所屬分類: 網絡編程
          主站蜘蛛池模板: 咸丰县| 墨玉县| 五指山市| 蒙自县| 安义县| 巫山县| 普陀区| 宜城市| 临江市| 宁城县| 新营市| 西乡县| 炎陵县| 会昌县| 天长市| 固原市| 荆门市| 阜阳市| 怀安县| 黄梅县| 朝阳县| 蒙山县| 五台县| 宁明县| 甘谷县| 全椒县| 全南县| 宁南县| 永仁县| 江华| 江源县| 西昌市| 宜宾市| 安多县| 墨脱县| 西乡县| 高要市| 磐安县| 彩票| 宜良县| 华安县|