1. 程式人生 > >C#網路程式設計(二)------多執行緒socket例項

C#網路程式設計(二)------多執行緒socket例項

伺服器端程式碼:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7. using System.Threading;  
  8. namespace multithreadservTest  
  9. {  
  10.     class Threadtcpserver  
  11.     {  
  12.         /* 本程式中採用了多執行緒技術,可以應付多客戶的需求。首先,程式的主執行緒也就是程式的入口即Main()函式,
     
  13.          * 當執行到Accept方法時,執行緒變會阻塞;當有新連線時,就建立相應的訊息服務執行緒。而主程式則繼續進行監聽, 
  14.          * 檢查有沒有新的連線進入。如果客戶端有向伺服器連線的請求,那麼就把連線控制代碼傳遞給接收的套接字。由於執行緒 
  15.          * 的排程和切換是非常快的,快得足以讓我們分辨不出程式的執行順序,所以從巨集觀上來講,可以說程式是並行執行 
  16.          * 的。但事實上,從微觀的角度上說,只是cpu飛快地排程執行緒,讓我們感覺好像可以同時接收連線和處理訊息一樣, 
  17.          * 但在一個時刻,只有一個執行緒是處於執行狀態的。
     
  18.          */
  19.         /// <summary>
  20.         /// 下面這段程式碼的業務邏輯是:
  21.         /// (1)建立套接字server,並將其與本地終結點iep進行繫結。然後,在13000埠上監聽是否
  22.                   有新的客戶端進行連線  
  23.         /// (2)在無限迴圈中有一個阻塞的方法Accept,該方法直到有新客戶端連線到伺服器上時,把
  24.                   客戶端的套接字資訊傳遞給client物件。否則,將阻塞 直到有客戶機進行連線。  
  25.         /// (3)ClientThread類負責客戶端與伺服器端之間的通訊。先把客戶端的套接字控制代碼傳遞給
  26.         ///       負責訊息服務的ClientThread類。然後,把ClientThread類 的ClientService方
  27.                   法委託給執行緒,並啟動執行緒。   
  28.         /// </summary>
  29.         private Socket server;  
  30.         public Threadtcpserver()  
  31.         {  
  32.             //初始化IP地址
  33.             IPAddress local=IPAddress.Parse("192.168.5.187");  
  34.             IPEndPoint iep = new IPEndPoint(local, 13000);  
  35.             server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,  
  36.             ProtocolType.Tcp);  
  37.             //將套接字與本地終結點繫結
  38.             server.Bind(iep);  
  39.             //在本地13000埠號上進行監聽
  40.             server.Listen(20);  
  41.             Console.WriteLine("等待客戶機進行連線......");  
  42.             while (true)  
  43.             {  
  44.                 //得到包含客戶端資訊的套接字
  45.                 Socket client = server.Accept();  
  46.                 //建立訊息服務執行緒物件
  47.                 ClientThread newclient = new ClientThread(client);  
  48.                 //把ClientThread類的ClientService方法委託給執行緒
  49.                 Thread newthread = new Thread(new ThreadStart(newclient.ClientService));  
  50.                 //啟動訊息服務執行緒
  51.                 newthread.Start();  
  52.             }  
  53.         }  
  54.         /// <summary>
  55.         /// (1)在建構函式中得到接收到的客戶套接字client,以後就通過service控制代碼處理訊息的接收
  56.          ///      和傳送。
  57.         /// (2)ClientService方法是委託給執行緒的,此方法進行訊息的處理工作。在這裡實現的功能是,
  58.         ///       先從客戶端接收一條訊息,然後把這條訊息轉換為大寫字母,並立即傳送一條應答的訊息,
  59.         ///      也就是所謂的echo技術,通常用來進行訊息之間的傳遞。
  60.         /// (3)還有就是通過connections變數來記錄活動的連線數。當有新增連線或斷開連線的情況發 
  61.         ///       生時,都會體現出connections的變化。
  62.        /// </summary>
  63.         publicclass ClientThread  
  64.         {  
  65.             //connections變量表示連線數
  66.             publicstaticint connections = 0;  
  67.             public Socket service;  
  68.             int i;  
  69.             //建構函式
  70.             public ClientThread(Socket clientsocket)  
  71.             {  
  72.                 //service物件接管對訊息的控制
  73.                 this.service = clientsocket;  
  74.             }  
  75.             publicvoid ClientService()  
  76.             {  
  77.                 String data = null;  
  78.                 byte[] bytes = newbyte[1024];  
  79.                 //如果Socket不是空,則連線數加1
  80.                 if (service != null)  
  81.                 {  
  82.                     connections++;  
  83.                 }  
  84.                 Console.WriteLine("新客戶連線建立:{0}個連線數", connections);  
  85.                 while((i=service.Receive(bytes))!=0)  
  86.                 {  
  87.                     data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);  
  88.                     Console.WriteLine("收到的資料:{0}", data);  
  89.                     //處理客戶端發來的訊息,這是轉化為大寫字母
  90.                     data = data.ToUpper();  
  91.                     byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);  
  92.                     //傳送一條應答訊息
  93.                     service.Send(msg);  
  94.                     Console.WriteLine("傳送的資料:{0}", data);  
  95.                 }  
  96.                 //關閉套接字
  97.                 service.Close();  
  98.                 connections--;  
  99.                 Console.WriteLine("客戶關閉連線:{0}個連線數", connections);  
  100.             }  
  101.             /// <summary>
  102.             /// Main函式十分簡單,生成和一個Threadtcpserver例項,然後建構函式就會一步一步地
  103.               /// 展開,開始執行具體的業務邏輯。
  104.             /// </summary>
  105.             /// <param name="args"></param>
  106.             staticvoid Main(string[] args)  
  107.             {  
  108.                 Threadtcpserver instance = new Threadtcpserver();  
  109.             }  
  110.         }  
  111.     }  
  112. }  

客戶端程式碼:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net;  
  6. using System.Net.Sockets;  
  7. namespace multithreadclientTest  
  8. {  
  9.     class Program  
  10.     {  
  11.         /// <summary>
  12.         /// 本程式程式碼的主要功能:
  13.         /// (1)建立套接字,並通過connect方法連線到本地終結點。當連線建立以後,便可以與伺服器進
  14.         ///       行通訊了。
  15.         /// (2)在客戶端上等待使用者輸入一條訊息,該訊息會發送到伺服器建立的訊息服務執行緒上
  16.         ///       的ClientService 方法上進行處理。在將該訊息轉化為大寫字母后,發還給客戶端。
  17.         ///       這是一個echo技術。如果在控制檯上輸入exit 接斷開與伺服器之間的連線。
  18.         /// </summary>
  19.         /// <param name="args"></param>
  20.         staticvoid Main(string[] args)  
  21.         {  
  22.             Socket client;  
  23.             byte[] buf = newbyte[1024];  
  24.             string input;  
  25.             IPAddress local = IPAddress.Parse("192.168.5.187");  
  26.             IPEndPoint iep = new IPEndPoint(local, 13000);  
  27.             try
  28.             {  
  29.                 client = new Socket(AddressFamily.InterNetwork, SocketType.Stream,  
  30.                 ProtocolType.Tcp);  
  31.                 client.Connect(iep);  
  32.             }  
  33.             catch (SocketException)  
  34.             {  
  35.                 Console.WriteLine("無法連線到伺服器!");  
  36.                 return;  
  37.             }  
  38.             finally
  39.             {  
  40.             }  
  41.             while (true)  
  42.             {  
  43.                 //在控制檯上輸入一