服務器端代碼:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- namespace multithreadservTest
- {
- class Threadtcpserver
- {
- /* 本程序中采用了多線程技術,可以應付多客戶的需求。首先,程序的主線程也就是程序的入口即Main()函數,
- * 當執行到Accept方法時,線程變會阻塞;當有新連接時,就創建相應的消息服務線程。而主程序則繼續進行監聽,
- * 檢查有沒有新的連接進入。如果客戶端有向服務器連接的請求,那么就把連接句柄傳遞給接收的套接字。由於線程
- * 的調度和切換是非常快的,快得足以讓我們分辨不出程序的運行順序,所以從宏觀上來講,可以說程序是並行執行
- * 的。但事實上,從微觀的角度上說,只是cpu飛快地調度線程,讓我們感覺好像可以同時接收連接和處理消息一樣,
- * 但在一個時刻,只有一個線程是處於運行狀態的。
- */
- /// <summary>
- /// 下面這段代碼的業務邏輯是:
- /// (1)創建套接字server,並將其與本地終結點iep進行綁定。然后,在13000端口上監聽是否
- 有新的客戶端進行連接
- /// (2)在無限循環中有一個阻塞的方法Accept,該方法直到有新客戶端連接到服務器上時,把
- 客戶端的套接字信息傳遞給client對象。否則,將阻塞 直到有客戶機進行連接。
- /// (3)ClientThread類負責客戶端與服務器端之間的通信。先把客戶端的套接字句柄傳遞給
- /// 負責消息服務的ClientThread類。然后,把ClientThread類 的ClientService方
- 法委托給線程,並啟動線程。
- /// </summary>
- private Socket server;
- public Threadtcpserver()
- {
- //初始化IP地址
- IPAddress local=IPAddress.Parse("192.168.5.187");
- IPEndPoint iep = new IPEndPoint(local, 13000);
- server = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
- ProtocolType.Tcp);
- //將套接字與本地終結點綁定
- server.Bind(iep);
- //在本地13000端口號上進行監聽
- server.Listen(20);
- Console.WriteLine("等待客戶機進行連接......");
- while (true)
- {
- //得到包含客戶端信息的套接字
- Socket client = server.Accept();
- //創建消息服務線程對象
- ClientThread newclient = new ClientThread(client);
- //把ClientThread類的ClientService方法委托給線程
- Thread newthread = new Thread(new ThreadStart(newclient.ClientService));
- //啟動消息服務線程
- newthread.Start();
- }
- }
- /// <summary>
- /// (1)在構造函數中得到接收到的客戶套接字client,以后就通過service句柄處理消息的接收
- /// 和發送。
- /// (2)ClientService方法是委托給線程的,此方法進行消息的處理工作。在這里實現的功能是,
- /// 先從客戶端接收一條消息,然后把這條消息轉換為大寫字母,並立即發送一條應答的消息,
- /// 也就是所謂的echo技術,通常用來進行消息之間的傳遞。
- /// (3)還有就是通過connections變量來記錄活動的連接數。當有新增連接或斷開連接的情況發
- /// 生時,都會體現出connections的變化。
- /// </summary>
- public class ClientThread
- {
- //connections變量表示連接數
- public static int connections = 0;
- public Socket service;
- int i;
- //構造函數
- public ClientThread(Socket clientsocket)
- {
- //service對象接管對消息的控制
- this.service = clientsocket;
- }
- public void ClientService()
- {
- String data = null;
- byte[] bytes = new byte[1024];
- //如果Socket不是空,則連接數加1
- if (service != null)
- {
- connections++;
- }
- Console.WriteLine("新客戶連接建立:{0}個連接數", connections);
- while((i=service.Receive(bytes))!=0)
- {
- data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
- Console.WriteLine("收到的數據:{0}", data);
- //處理客戶端發來的消息,這是轉化為大寫字母
- data = data.ToUpper();
- byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
- //發送一條應答消息
- service.Send(msg);
- Console.WriteLine("發送的數據:{0}", data);
- }
- //關閉套接字
- service.Close();
- connections--;
- Console.WriteLine("客戶關閉連接:{0}個連接數", connections);
- }
- /// <summary>
- /// Main函數十分簡單,生成和一個Threadtcpserver實例,然后構造函數就會一步一步地
- /// 展開,開始執行具體的業務邏輯。
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- Threadtcpserver instance = new Threadtcpserver();
- }
- }
- }
- }
客戶端代碼:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Net;
- using System.Net.Sockets;
- namespace multithreadclientTest
- {
- class Program
- {
- /// <summary>
- /// 本程序代碼的主要功能:
- /// (1)創建套接字,並通過connect方法連接到本地終結點。當連接建立以后,便可以與服務器進
- /// 行通訊了。
- /// (2)在客戶端上等待用戶輸入一條消息,該消息會發送到服務器創建的消息服務線程上
- /// 的ClientService 方法上進行處理。在將該消息轉化為大寫字母后,發還給客戶端。
- /// 這是一個echo技術。如果在控制台上輸入exit 接斷開與服務器之間的連接。
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- Socket client;
- byte[] buf = new byte[1024];
- string input;
- IPAddress local = IPAddress.Parse("192.168.5.187");
- IPEndPoint iep = new IPEndPoint(local, 13000);
- try
- {
- client = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
- ProtocolType.Tcp);
- client.Connect(iep);
- }
- catch (SocketException)
- {
- Console.WriteLine("無法連接到服務器!");
- return;
- }
- finally
- {
- }
- while (true)
- {
- //在控制台上輸入一條消息
- input = Console.ReadLine();
- //輸入exit,可以斷開與服務器的連接
- if (input == "exit")
- {
- break;
- }
- client.Send(Encoding.ASCII.GetBytes(input));
- //得到實際收到的字節總數
- int rec = client.Receive(buf);
- Console.WriteLine(Encoding.ASCII.GetString(buf, 0, rec));
- }
- Console.WriteLine("斷開與服務器的連接......");
- client.Close();
- }
- }
- }
程序執行部分截圖: