Visual C#.Net網絡程序開發-Tcp篇(2)

Visual C#.Net網絡程序開發-Tcp篇(2)
作者: 宋華   www.ASPCool.com 時間:2002-5-5 17:36:39  閱讀次數:6352

    
  前面我們說,TcpClient類創建在Socket之上,在Tcp服務方面提供了更高層次的抽象,體現在網絡數據的發送和接受方面,是TcpClient使用標準的Stream流處理技術,使得它讀寫數據更加方便直觀,同時,.Net框架負責提供更豐富的結構來處理流,貫穿於整個.Net框架中的流具有更廣泛的兼容性,構建在更一般化的流操作上的通用方法使我們不再需要困惑於文件的實際內容(HTML、XML 或其他任何內容),應用程序都將使用一致的方法(Stream.Write、Stream.Read) 發送和接收數據。另外,流在數據從 Internet 下載的過程中提供對數據的即時訪問,可以在部分數據到達時立即開始處理,而不需要等待應用程序下載完整個數據集。.Net中通過NetworkStream類實現了這些處理技術。
  
  NetworkStream 類包含在.Net框架的System.Net.Sockets 命名空間裏,該類專門提供用於網絡訪問的基礎數據流。NetworkStream 實現通過網絡套接字發送和接收數據的標準.Net 框架流機制。NetworkStream 支持對網絡數據流的同步和異步訪問。NetworkStream 從 Stream 繼承,後者提供了一組豐富的用於方便網絡通訊的方法和屬性。
  
  同其它繼承自抽象基類Stream的所有流一樣,NetworkStream網絡流也可以被視爲一個數據通道,架設在數據來源端(客戶Client)和接收端(服務Server)之間,而後的數據讀取及寫入均針對這個通道來進行。
  
  .Net框架中,NetworkStream流支持兩方面的操作:
  
  1、 寫入流。寫入是從數據結構到流的數據傳輸。
  
  示 意 圖
  
  15632.gif
  2、讀取流。讀取是從流到數據結構(如字節數組)的數據傳輸。
  
  示 意 圖
  15633.gif
  與普通流Stream不同的是,網絡流沒有當前位置的統一概念,因此不支持查找和對數據流的隨機訪問。相應屬性CanSeek 始終返回 false,而 Seek 和 Position 方法也將引發 NotSupportedException。
  
  基於Socket上的應用協議方面,你可以通過以下兩種方式獲取NetworkStream網絡數據流:
  
  1、使用NetworkStream構造函數:public NetworkStream(Socket, FileAccess, bool);(有重載方法),它用指定的訪問權限和指定的 Socket 所屬權爲指定的 Socket 創建 NetworkStream 類的新實例,使用前你需要創建Socket對象實例,並通過Socket.Connect方法建立與遠程服務端的連接,而後纔可以使用該方法得到網絡傳輸流。示例如下:
  
  Socket s=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//創建客戶端Socket對象實例
   try{
   s.Connect("www.tuha.net",4088);//建立與遠程主機的連接
   }
   catch(Exception e){
   MessageBox.show("連接錯誤:" +e.Message);
   }
   try{
   NetworkStream stream=new NetworkStream(s,FileAccess.ReadWrite,false);//取得網絡傳輸流
   }
  
  
  2、通過TcpClient.GetStream方法:public NetworkStream etStream();它返回用於發送和接收數據的基礎網絡流NetworkStream。GetStream 通過將基礎 Socket 用作它的構造函數參數來創建 NetworkStream 類的實例。使用前你需要先創TcpClient對象實例並建立與遠程主機的連接,示例如下:
  
  TcpClient tcpClient = new TcpClient();//創建TcpClient對象實例
   Try{
   tcpClient.Connect("www.tuha.net",4088);//嘗試與遠程主機相連
   }
   catch(Exception e){
   MessageBox.Show("連接錯誤:"+e.Message);
   }
   try{
   NetworkStream stream=tcpClient.GetStream();//獲取網絡傳輸流
   }
   catch(Exception e)
   {
   MessageBox.Show("TcpClient錯誤:"+e.Message);
   }
  
  
  通過以上方法得到NetworkStream網絡流之後,你就可以使用標準流讀寫方法Write和Read來發送和接受數據了。
  
  以上是.Net下使用TcpClient類實現客戶端編程的技術資料,爲了向客戶端提供這些服務,我們還需要編制相應的服務端程序,前一篇《Visual C#.Net網絡程序開發-Socket篇》上曾經提到, Socket作爲其他網絡協議的基礎,既可以面向客戶端開發,也可以面向服務端開發,在傳輸層面上使用較多,而在應用協議層面上,客戶端我們採用構建於Socket類之上的TcpClient取代Socket;相應地,構建於Socket之上的TcpListener提供了更高理念級別的 TCP 服務,使得我們能更方便地編寫服務端應用程序。正是因爲這樣的原因,像FTP 和 HTTP 這樣的應用層協議都是在 TcpListener 類的基礎上建立的。
  
  .Net中的TCPListener 用於監視TCP 端口上的傳入請求,通過綁定本機IP地址和相應端口(這兩者應與客戶端的請求一致)創建TcpListener對象實例,並由Start方法啓動偵聽;當TcpListener偵聽到用戶端的連接後,視客戶端的不同請求方式,通過AcceptTcpClient 方法接受傳入的連接請求並創建 TcpClient 以處理請求,或者通過AcceptSocket 方法接受傳入的連接請求並創建 Socket 以處理請求。最後,你需要使用 Stop 關閉用於偵聽傳入連接的 Socket,你必須也關閉從 AcceptSocket 或 AcceptTcpClient 返回的任何實例。這個過程詳細解說如下:
  
  首先,創建TcpListener對象實例,這通過TcpListener類的構造方法來實現:
  
  public TcpListener(port);//指定本機端口
  public TcpListener(IPEndPoint)//指定本機終結點
  public TcpListener(IPAddress,port)//指定本機IP地址及端口
  
  
  以上方法中的參數在前面多次提到,這裏不再細述,唯一需要提醒的是,這些參數均針對服務端主機。下面的示例演示創建 TcpListener 類的實例:
  
  IPHostEntry ipInfo=Dns.Resolve("127.0.0.1");//主機信息
   IPAddressList[] ipList=ipInfo.IPAddressList;//IP數組
   IPAddress ip=ipList[0];//IP
   try{
   TcpListener tcpListener = new TcpListener(ipAddress, 4088);//創建TcpListener對象實例以偵聽用戶端連接
   }
   catch ( Exception e){
   MessageBox.Show("TcpListener錯誤:"+e.Message);
   }
  
  
  隨後,你需要調用Start方法啓動偵聽:
  
  public void Start();
  
  
  其次,當偵聽到有用戶端連接時,需要接受掛起的連接請求,這通過調用以下兩方法之一來完成連接:
  
  public Socket AcceptSocket();
  public TcpClient AcceptTcpClient();
  
  
  前一個方法返回代表客戶端的Socket對象,隨後可以通過Socket 類的 Send 和 Receive 方法與遠程計算機通訊;後一個方法返回代表客戶端的TcpClient對象,隨後使用上面介紹的 TcpClient.GetStream 方法獲取 TcpClient 的基礎網絡流 NetworkStream,並使用流讀寫Read/Write方法與遠程計算機通訊。
  
  最後,請記住關閉偵聽器:public void Stop();
  
  同時關閉其他連接實例:public void Close();
  
  下面的示例完整體現了上面的過程:
  
  bool done = false;
   TcpListener listener = new TcpListener(13);// 創建TcpListener對象實例(13號端口提供時間服務)
   listener.Start();//啓動偵聽
   while (!done) {//進入無限循環以偵聽用戶連接
   TcpClient client = listener.AcceptTcpClient();//偵聽到連接後創建客戶端連接TcpClient
   NetworkStream ns = client.GetStream();//得到網絡傳輸流
   byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString());//預發送的內容(此爲服務端時間)轉換爲字節數組以便寫入流
   try {
   ns.Write(byteTime, 0, byteTime.Length);//寫入流
   ns.Close();//關閉流
   client.Close();//關閉客戶端連接
   }
  catch (Exception e) {
   MessageBox.Show("流錯誤:"+e.Message)
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章