程式簡介
好久沒寫部落格了,最近時間比較充足.於是便打算把之前的聊天程式功能改進下,增加了一個服務端給用戶端群發資訊的功能.
原理
首先我們需要擷取串連用戶端的IP和Port,並添加到用戶端列表裡作為每個用戶端的唯一標識.然後通過相應用戶端的Socket.Send()方法將資訊發送出去.
服務端給用戶端的資訊群發與服務端給單個用戶端的資訊發送原理是一樣的,通過遍曆用戶端列表裡的所有用戶端標識,然後把資訊一個個發送出去.
介面設計 - 用戶端
介面設計 - 服務端
代碼實施 - 用戶端
用戶端沒有做什麼功能改進,這裡就不貼代碼了,需要看的學友可以到隨筆後面下載原始碼.
代碼實施 - 服務端
這裡將手動輸入服務端IPv4地址改為了程式自動擷取
/// <summary> /// 擷取本地IPv4地址 /// </summary> /// <returns>本地IPv4地址</returns> public IPAddress GetLocalIPv4Address() { IPAddress localIPv4 = null; //擷取本機所有的IP地址清單 IPAddress[] ipAddressList = Dns.GetHostAddresses(Dns.GetHostName()); foreach (IPAddress ipAddress in ipAddressList) { //判斷是否是IPv4地址 if (ipAddress.AddressFamily == AddressFamily.InterNetwork) //AddressFamily.InterNetwork表示IPv4 { localIPv4 = ipAddress; } else continue; } return localIPv4; }
為了方便後期給所有訪問的用戶端群發資訊,我們需要用過通過監聽用戶端來擷取所有訪問用戶端的IP地址和連接埠號碼,並組成每個訪問用戶端的唯一標識clientName 用於顯示在用戶端列表上;用戶端唯一標識還有個作用就是服務端可以選擇性的給單獨某個用戶端發送資訊.
//用於儲存所有通訊用戶端的Socket Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>(); //建立與用戶端建立串連的通訊端 Socket socConnection = null; string clientName = null; //建立訪問用戶端的名字 IPAddress clientIP; //訪問用戶端的IP int clientPort; //訪問用戶端的連接埠號碼 /// <summary> /// 持續不斷監聽用戶端發來的請求, 用於不斷擷取用戶端發送過來的連續資料資訊 /// </summary> private void WatchConnecting() { while (true) { try { socConnection = socketWatch.Accept(); } catch (Exception ex) { txtMsg.AppendText(ex.Message); //提示通訊端監聽異常 break; } //擷取訪問用戶端的IP clientIP = (socConnection.RemoteEndPoint as IPEndPoint).Address; //擷取訪問用戶端的Port clientPort = (socConnection.RemoteEndPoint as IPEndPoint).Port; //建立訪問用戶端的唯一標識 由IP和連接埠號碼組成 clientName = "IP: " + clientIP +" Port: "+ clientPort; lstClients.Items.Add(clientName); //在用戶端列表添加該訪問用戶端的唯一標識 dicSocket.Add(clientName, socConnection); //將用戶端名字和通訊端添加到添加到資料字典中 //建立通訊線程 ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg); Thread thread = new Thread(pts); thread.IsBackground = true; //啟動線程 thread.Start(socConnection); txtMsg.AppendText("IP: " + clientIP + " Port: " + clientPort + " 的用戶端與您串連成功,現在你們可以開始通訊了...\r\n"); } }
服務端向用戶端發送資訊,在沒有選擇具體某個用戶端的情況下,預設群發. 如果選擇了具體某個用戶端,則單獨向該用戶端發送資訊.
/// <summary> /// 發送資訊到用戶端的方法 /// </summary> /// <param name="sendMsg">發送的字串資訊</param> private void ServerSendMsg(string sendMsg) { sendMsg = txtSendMsg.Text.Trim(); //將輸入的字串轉換成 機器可以識別的位元組數組 byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg); //向用戶端列表選中的用戶端發送資訊 if (!string.IsNullOrEmpty(lstClients.Text.Trim())) { //獲得相應的通訊端 並將位元組數組資訊發送出去 dicSocket[lstClients.Text.Trim()].Send(arrSendMsg); //通過Socket的send方法將位元組數組發送出去 txtMsg.AppendText("您在 " + GetCurrentTime() + " 向 IP: " + clientIP + " Port: " + clientPort + " 的用戶端發送了:\r\n" + sendMsg + "\r\n"); } else //如果未選擇任何用戶端 則預設為群發資訊 { //遍曆所有的用戶端 for (int i = 0; i < lstClients.Items.Count; i++) { dicSocket[lstClients.Items[i].ToString()].Send(arrSendMsg); } txtMsg.AppendText("您在 " + GetCurrentTime() + " 群發了資訊:\r\n" + sendMsg + " \r\n"); } }
運行程式
1.首先啟動服務端並串連各個用戶端
2.服務端向所有用戶端群發資訊
3.向指定的用戶端發送資訊
這樣,服務端向用戶端群發資訊的功能就做好了.如果大家感興趣,可以結合第2篇-檔案發送 來做個服務端向用戶端群發檔案的功能
附上原始碼
服務端ChatServer3.zip 用戶端 ChatClient3.zip
相關推薦
- 基於C# Winform的簡易聊天程式[第一篇-兩端通訊]
- 基於C# Winform的簡易聊天程式[第二篇-檔案發送]