C# 非同步通訊 網路聊天程式開發 區域網路聊天室開發

來源:互聯網
上載者:User

標籤:visual   互動   位元組   src   網路服務   event   handle   說明   orm   

Prepare

 本文將使用一個NuGet公開的組件技術來實現一個區域網路聊天程式,利用組件提供的高效能非同步網路機制實現,免去了手動編寫底層的困擾,易於二次開發,擴充自己的功能。

 

在Visual Studio 中的NuGet管理器中可以下載安裝,也可以直接在NuGet控制台輸入下面的指令安裝:

Install-Package HslCommunication

 

NuGet安裝教程  http://www.cnblogs.com/dathlin/p/7705014.html

支援人員QQ群:592132877 (組件的版本更新細節也將第一時間在群裡發布)

 

Summary

之前已經有篇部落格說明了同步網路通訊的開發,同步網路通訊適用於什麼樣的情境呢,適用於用戶端向伺服器請求資料,必須有資料返回的情況,無論成功還是失敗。地址:http://www.cnblogs.com/dathlin/p/7697782.html

而非同步網路通訊適用於什麼情況呢,適用於伺服器進行群發資料的時候,比如發送訊息給所有的線上用戶端,為了更好的說明非同步網路通訊的實現機制,開發一個多用戶端的區域網路聊天程式來示範非同步作業。

特性如下:

  • 區域網路聊天室支援多人線上,上限取決於伺服器的電腦效能。
  • 支援使用者名稱登入,支援重複的使用者名稱登入。
  • 支援顯示所有線上用戶端的資訊顯示,包括線上時間,上線時間,ip地址,使用者名稱等等。
  • 支援伺服器主動發訊息給用戶端。
  • 支援伺服器強制關閉用戶端。
  • 支援其他人的上下線資訊跟蹤。

 

本聊天程式是基於C-S架構設計的,需要建立3個項目,一個伺服器項目,用來中轉所有的訊息的,一個是用戶端項目,也就是實際的聊天程式,本次項目還顯示所有線上的用戶端資訊,ip地址,名字。

至於賬戶,本次不採用任何的使用者名稱密碼登入機制,就採用簡易化處理,直接輸入一個名字即可,當然,你也可以更改成使用者名稱密碼登入的機制,也不是特別困難。

簡易的聊天程式不支援圖片,表情包的發送接收,這部分實現起來不是同一個次元的,這部分以後攻克了再開新的博文。

 

------------> 小插曲

如果需要更複雜的功能,比如賬戶的登入,密碼修改,版本控制,賬戶支援頭像等等,一個基於本組件擴充出來的CS架構的基礎模版項目,二次基於此進行方便的二次開發,該項目使用了好幾處的檔案管理:

https://github.com/dathlin/ClientServerProject

一個C-S模版,該模版由三部分的程式組成,一個服務端啟動並執行程式,一個用戶端啟動並執行程式,還有一個公用的組件,實現了基礎的賬戶管理功能,版本控制,軟體升級,公告管理,訊息群發,共用檔案上傳下載,批量檔案傳送功能。具體的操作方法見示範就行。本項目的一個目標是:提供一個基礎的中小型系統的C-S架構,用戶端有四種模式,無縫整合訪問,winform版本,wpf版本,asp.net mvc版本,Android版本。方便企業進行中小型系統的二次開發和個人學習。

 

 

Reference

 

日誌組件所有的功能類都在 HslCommunication 和 HslCommunication.Enthernet 命名空間,所以再使用之前先添加:在伺服器程式和用戶端程式都要添加

using HslCommunication;using HslCommunication.Enthernet;

 

Start Program

首先先建立三個項目,server項目,client項目,common項目,然後使用Nuget將用戶端和伺服器兩個項目都安裝組件,然後切換到伺服器程式,接下來就是真的建立程式了。

  • common項目:存放一些伺服器和用戶端共同用到的類。
  • server項目:訊息路由中心。所有的用戶端發送的訊息都先經過伺服器轉寄。
  • client項目:和使用者互動的用戶端,接受使用者的輸入並且顯示出來。

在整個項目中,核心部分就是網路通訊了,需要實現用戶端向伺服器發送訊息,這個相對比較好實現,因為伺服器的ip地址和連接埠都是公開的。但是用戶端的ip和連接埠是未知的,因為我們要實現任意的電腦都能登入用戶端。所以我們需要使用HslCommunication來方便的實現這些操作。

 

在server端和client端都需要安裝HslCommunication組件。因為我們要實現在用戶端和伺服器端進行通訊,通訊功能眾多,所以需要進行約定,訊息的id,我們最終根據訊息的id來區分不同的訊息。

  • 1    系統訊息,用於顯示誰誰誰上線了,誰誰誰下線了
  • 2    是使用者發送的訊息,在聊天視窗進行顯示的
  • 3    用戶端線上資訊,所以線上用戶端的資訊
  • 4    強制用戶端下線,用於伺服器向用戶端發送關閉的指令,用戶端接收到後退出程式。

綜上所述,這個項目已經初步成型,而且通過訊息id可以實現其他自己功能擴充,可以實現任何的互動操作。不一定是聊天系統,各種資料同步機制,推送機制,區域網路機制的遊戲程式也可以實現。

 

本項目的原始碼地址如下:https://github.com/dathlin/NetChatRoom

Server

先填寫核心塊

        #region 核心網路服務相關        private NetComplexServer complexServer;        private void ComplexServerInitialization()        {            complexServer = new NetComplexServer();                                             // 執行個體化            complexServer.KeyToken = new Guid("91625bad-d581-44ab-b121-ffff5bcb83fb");          // 設定令牌,提升安全性            complexServer.LogNet = new HslCommunication.LogNet.LogNetSingle("log.txt");         // 設定日誌記錄,如果不需要,可以刪除            complexServer.ClientOnline += ComplexServer_ClientOnline;                           // 用戶端上線時觸發            complexServer.ClientOffline += ComplexServer_ClientOffline;                         // 用戶端下線時觸發            complexServer.AllClientsStatusChange += ComplexServer_AllClientsStatusChange;       // 只要有用戶端上線或下線就觸發            complexServer.AcceptString += ComplexServer_AcceptString;                           // 用戶端發來訊息時觸發            complexServer.ServerStart(12345);                                                   // 啟動服務,需要選擇一個連接埠        }        private void ComplexServer_AllClientsStatusChange(string object1)        {                    }        private void ComplexServer_AcceptString(AsyncStateOne object1, NetHandle object2, string object3)        {            // 我們規定            // 1 是系統訊息,            // 2 是使用者發送的訊息            // 3 用戶端線上資訊            // 4 強制用戶端下線            // 當你的訊息頭種類很多以後,可以在一個統一的類中心進行規定            if (object2 == 2)            {                // 來自用戶端的訊息,就只有這麼一種情況                NetMessage msg = new NetMessage()                {                    FromName = object1.LoginAlias,                    Time = DateTime.Now,                    Type = "string",                    Content = object3,                };                // 群發出去                complexServer.SendAllClients(2, JObject.FromObject(msg).ToString());            }        }        private void ComplexServer_ClientOffline(AsyncStateOne object1, string object2)        {            // 用戶端下線,發送訊息給用戶端            complexServer.SendAllClients(1, object1.IpAddress + " " + object1.LoginAlias + " : " + object2);            // 發送線上資訊            complexServer.SendAllClients(3, RemoveOnLine(object1.ClientUniqueID));            // 在主介面顯示資訊            ShowMsg(object1.IpAddress + " " + object1.LoginAlias + " : " + object2);            ShowOnlineClient( );        }        private void ComplexServer_ClientOnline(AsyncStateOne object1)        {            // 用戶端上線,發送訊息給用戶端            complexServer.SendAllClients(1, object1.IpAddress + " " + object1.LoginAlias + " : 上線");            // 發送線上資訊            NetAccount account = new NetAccount()            {                Guid = object1.ClientUniqueID,                Ip = object1.IpAddress,                Name = object1.LoginAlias,                OnlineTime = DateTime.Now.ToString(),            };            complexServer.SendAllClients(3,  AddOnLine(account));            // 在主介面顯示資訊            ShowMsg(object1.IpAddress + " " + object1.LoginAlias + " : 上線");            ShowOnlineClient( );        }        #endregion

 在此處有個功能是實現對線上用戶端的資訊記錄,包含了許多的資訊,並可以實現擴充

        #region 線上用戶端資訊實現塊        private List<NetAccount> all_accounts = new List<NetAccount>();        private object obj_lock = new object();        // 新增一個使用者賬戶到線上用戶端        private string AddOnLine(NetAccount item)        {            string result = string.Empty;            lock(obj_lock)            {                all_accounts.Add(item);                result = JArray.FromObject(all_accounts).ToString();            }            return result;        }        // 移除線上賬戶並返回相應的線上資訊        private string RemoveOnLine(string guid)        {            string result = string.Empty;            lock (obj_lock)            {                for (int i = 0; i < all_accounts.Count; i++)                {                    if(all_accounts[i].Guid == guid)                    {                        all_accounts.RemoveAt(i);                        break;                    }                }                result = JArray.FromObject(all_accounts).ToString();            }            return result;        }        #endregion

 關於線上資訊的類

    /// <summary>    /// 擴充實現的賬戶資訊,記錄唯一標記,ip地址,上線時間,名字    /// </summary>    public class NetAccount    {        /// <summary>        /// 唯一ID        /// </summary>        public string Guid { get; set; }        /// <summary>        /// Ip地址        /// </summary>        public string Ip { get; set; }        /// <summary>        /// 上線時間        /// </summary>        public string OnlineTime { get; set; }        /// <summary>        /// 名稱        /// </summary>        public string Name { get; set; }        /// <summary>        /// 字串標識形式        /// </summary>        /// <returns></returns>        public override string ToString()        {            return "[" + Ip + "] : " + Name;        }    }

 下面示範在伺服器端如何發送一個系統訊息給所有用戶端

        private void userButton1_Click(object sender, EventArgs e)        {            // 伺服器發送系統訊息到用戶端            if(!string.IsNullOrEmpty(textBox2.Text))            {                // 來自用戶端的訊息,就只有這麼一種情況                NetMessage msg = new NetMessage()                {                    FromName = "系統",                    Time = DateTime.Now,                    Type = "string",                    Content = textBox2.Text,                };                // 群發出去                complexServer.SendAllClients(2, JObject.FromObject(msg).ToString());            }        }

 這樣就可以實現訊息的發送了。

 

Client

先填寫核心塊

       #region 用戶端網路塊        private NetComplexClient net_socket_client = new NetComplexClient();        private void Net_Socket_Client_Initialization()        {            try            {                net_socket_client.KeyToken = new Guid("91625bad-d581-44ab-b121-ffff5bcb83fb");          // 設定令牌,必須與已連線的服務器令牌一致                net_socket_client.EndPointServer = new System.Net.IPEndPoint(                    System.Net.IPAddress.Parse("127.0.0.1"),12345);                                     // 已連線的服務器的地址,必須和伺服器端的資訊對應                net_socket_client.ClientAlias = LoginName;                                              // 傳入賬戶名                net_socket_client.AcceptString += Net_socket_client_AcceptString;                       // 接收到字串資訊時觸發                net_socket_client.ClientStart();            }            catch (Exception ex)            {                SoftBasic.ShowExceptionMessage(ex);            }        }        /// <summary>        /// 接收到伺服器的位元組資料的回調方法        /// </summary>        /// <param name="state">網路連接對象</param>        /// <param name="customer">使用者自訂的指令頭,用來區分資料用途</param>        /// <param name="data">資料</param>        private void Net_socket_client_AcceptString(AsyncStateOne state, NetHandle customer, string data)        {            // 我們規定            // 1 是系統訊息,            // 2 是使用者發送的訊息            // 3 用戶端線上資訊            // 4 退出指令            // 當你的訊息頭種類很多以後,可以在一個統一的類中心進行規定            if (customer == 1)            {                ShowSystemMsg(data);            }            else if(customer == 2)            {                ShowMsg(data);            }            else if(customer == 3)            {                ShowOnlineClient(data);            }            else if(customer == 4)            {                // 退出系統                QuitSystem( );            }        }        #endregion

 使用者在輸入發送資訊的時候,就調用如下的方法:

        // 發送訊息        private void userButton1_Click(object sender, EventArgs e)        {            if (string.IsNullOrEmpty(textBox3.Text)) return;            net_socket_client.Send(2, textBox3.Text);            textBox3.Clear();        }

 

 

具體的代碼邏輯還需要參照github上的原始碼。

C# 非同步通訊 網路聊天程式開發 區域網路聊天室開發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.