Avalonia 實現跨平臺的IM即時通訊、語音視頻通話(源碼,支持信創國產OS,統信、銀河麒麟)

      在 Avalonia 如火如荼的現在,之前使用CPF實現的簡單IM,非常有必要基於 Avalonia 來實現了。Avalonia 在跨平臺上的表現非常出色,對信創國產操作系統(像銀河麒麟、統信UOS、Deepin等)也很不錯。

      現在,我們就來使用 Avalonia 實現一個跨平臺的簡單IM,除了文字聊天外,還可以語音視頻通話。廢話不多說,我們開始吧!

      下圖是這個簡單IM的Avalonia客戶端在國產統信UOS上的運行的截圖:

      

一. IM 即時通訊系統主要功能

      這個簡單的IM系統實現了以下功能:

1.基礎功能、文字聊天

(1)客戶端用戶上下線時,通知其他在線用戶。

(2)當客戶端與服務端網絡斷開時,進行自動重連,當網絡恢復後,重連成功。

(3)所有在線用戶之間可以進行文字聊天(支持表情,支持撤回消息、刪除消息)。

(4)文件傳送。

2.語音視頻聊天、遠程桌面

(1)一方發起視頻對話請求,對方同意後,即可開始視頻對話。

(2)在對話的過程中,任何一方都可以掛斷,以終止對話。

(3)在對話的過程中,任何一方掉線,都會自動終止對話。

(4)雙擊視頻窗口,會全屏顯示視頻,按esc退出全屏。

(5)遠程桌面或遠程協助功能,也是跟視頻聊天同樣的流程,不再贅述。

二.開發環境

1.開發工具:

Visual Studio 2022

2. 開發框架:

.NET Core 3.1

3.開發語言:

C#

4.其它框架:

Avalonia UI 框架(版本:0.10.22)、ESFramework 通信框架 (版本:7.2)

注:建議 Avalonia 使用0.10.*的版本,精簡而且很穩定,而最新的11.0的版本太龐大了。

三.具體實現

下面我們講一下Demo中核心的代碼實現,大家從文末下載源碼並對照着源碼看,會更清楚些。

1.自定義消息類型 InformationTypes

       若要實現上述功能列表中列出來的所有功能,我們先要定義相應的通信消息的消息類型,如下所示:

    public static class InformationTypes
    {
        /// <summary>
        /// 文字(表情)聊天信息
        /// </summary>
        public const int TextChat = 0;

        /// <summary>
        /// 文字(表情)聊天信息 (由服務端轉發給消息接收方)
        /// </summary>
        public const int TextChat4Transit = 1;

        /// <summary>
        /// 圖片聊天信息
        /// </summary>
        public const int ImageChat = 2;

        /// <summary>
        /// 收到消息發送者 撤回消息請求
        /// </summary>
        public const int RecallMsg = 3;

        /// <summary>
        /// 客戶端異步調用服務端
        /// </summary>
        public const int ClientSyncCallServer = 4;

        /// <summary>
        /// 視頻請求 5
        /// </summary>
        public const int VideoRequest = 5;

        /// <summary>
        /// 回覆視頻請求的結果 6
        /// </summary>
        public const int VideoResult = 6;

        /// <summary>
        /// 通知對方 掛斷 視頻連接 7
        /// </summary>
        public const int CloseVideo = 7;

        /// <summary>
        /// 通知好友 網絡原因,導致 視頻中斷 8
        /// </summary>
        public const int NetReasonCloseVideo = 8;

        /// <summary>
        /// 通知對方(忙線中) 掛斷 視頻連接 9
        /// </summary>
        public const int BusyLine = 9;

        /// <summary>
        /// 收到遠程協助請求
        /// </summary>
        public const int AssistReceive = 10;

        /// <summary>
        /// 協助方拒絕遠程協助
        /// </summary>
        public const int AssistGusetReject = 11;

        /// <summary>
        /// 協助方同意遠程協助
        /// </summary>
        public const int AssistGusetAgree = 12;

        /// <summary>
        /// 請求方關閉遠程協助
        /// </summary>
        public const int AssistOwnerClose = 13;

        /// <summary>
        /// 協助方關閉遠程協助
        /// </summary>
        public const int AssistGusetClose = 14;
    }

       在約定好消息類型之後,我們就可以實現業務邏輯功能了。 

2.定義協議類

      信息類型定義好後,我們接下來定義信息協議。

      對於聊天消息(InformationTypes.EmotionTextChat),專門定義了一個協議類:ChatMessageRecord。     

    public class ChatMessageRecord
    {
        public string Guid { get; set; }

        public DateTime MessageTime { get; set; }

        public string SpeakerID { get; set; }

        public string ListenerID { get; set; }

        public ChatMessageType ChatMessageType { get; set; }

        public string ContentStr { get; set; }

        public byte[] ImgData { get; set; }

        public string FilePath { get; set; }
    }

      對於同步調用(InformationTypes.ClientSyncCallServer),我們示例的是向服務器請求加法運算的結果,協議類用的是MathModel。

3.實現自定義信息處理器

      客戶端的MainForm實現了ICustomizeHandler接口,其主要實現HandleInformation方法,來處理收到的聊天信息和振動提醒。

  void HandleInformation(string sourceUserID, int informationType, byte[] info);

      服務端的CustomizeHandler實現了服務端的ICustomizeHandler接口,其主要實現HandleQuery方法來處理來自客戶端的同步調用(InformationTypes.ClientCallServer)。

  byte[] HandleQuery(string sourceUserID, int informationType, byte[] info);

4.服務端驗證用戶登錄的帳號

       服務端的BasicHandler類實現IBasicHandler接口,以驗證登錄用戶的賬號密碼。

    public class BasicHandler : IBasicHandler
    { 
        /// <summary>
        /// 此處驗證用戶的賬號和密碼。返回true表示通過驗證。
        /// </summary>  
        public bool VerifyUser(ClientType clientType, string systemToken, string userID, string password, out string failureCause)
        {
            failureCause = "";
            return true;
        }

        public string HandleQueryBeforeLogin(AgileIPE clientAddr, int queryType, string query)
        {
            return "";
        }
    }

       本demo中,假設所有的驗證都通過,所以驗證方法直接返回true。

5.客戶端實現文字聊天功能

     通過IRapidPassiveEngine的 CustomizeOutter 的 Send 方法來發送文字表情聊天消息。 

     在發送文字聊天消息時,有兩個發送按鈕,“發送1”和“發送2”,分別演示了兩種發送消息給對方的方式:

(1)直接發給對方。(若P2P通道存在,則經由P2P通道發送)

        internal static void SendTextMsgToClient(ChatMessageRecord record)
        {
            try
            {
                string cont = JsonConvert.SerializeObject(record);
                byte[] recordInfo = Encoding.UTF8.GetBytes(cont);
                //使用Tag攜帶 接收者的ID
                App.PassiveEngine.CustomizeOutter.Send(record.ListenerID, InformationTypes.TextChat4Transit, recordInfo);
            }
            catch (Exception e)
            {
                logger.Log(e, "GlobalHelper.SendTextMsgToClient", ErrorLevel.Standard);
            }
        }

      聊天消息 ChatMessageRecord 對象先由JSON序列化成字符串,然後在使用UTF-8轉成字節數組,然後通過通信引擎的CustomizeOutter發送出去。

(2)先發給服務器,再由服務器轉發給對方。     

      具體實現,大家去參看源碼,這裏就不再贅述了。

6.客戶端實現語音視頻通話功能

         語音視頻通話實際運行起來後的效果如下所示:

 

         我們先簡單描述一下實現視頻對話流程的要點,更詳細的細節請查閱源代碼。

(1)發起方發送InformationTypes.VideoRequest類型的信息給對方,以請求視頻對話。

     程序中是在 VideoChatWindow 窗口顯示的時候,來做這件事的:

        protected override void OnInitialized()
        {
            base.OnInitialized(); 
            this.SetWindowStats();
            if (!this.IsWorking)
            {
                VideoController.Singleton.SendMessage(this.DestID, InformationTypes.VideoRequest, null);
                CommonHelper.AddSystemMsg(this.DestID, "向對方發起視頻通話邀請");
            }
        }

(2)接收方收到請求後,界面提示用戶是同意還是拒絕,用戶選擇後,將發送InformationTypes.VideoResult類型的信息給請求方,信息的內容是一個bool值,true表示同意,false表示拒絕。

(3)發起方收到回覆,如果回覆爲拒絕,則界面給出對應的提示;如果回覆爲同意,則進入(4)。

(4)先說接收方,如果同意視頻,則發送回覆後,立即調用DynamicCameraConnector和MicrophoneConnector的Connect方法,連接到對方的攝像頭、麥克風。

        internal void BeginConnect()
        {
            UiSafeInvoker.ActionOnUI(() =>
            {
                string tip = this.IsWorking ? "已同意對方的視頻通話" : "對方同意了你的視頻通話請求";
                CommonHelper.AddSystemMsg(this.DestID, tip);
                this.IsWorking = true;
                this.NotifyOther = true;
                this.Title = this.title.Text = this.RepeatedCallTip(false);
                this.startTime = DateTime.Now;
                this.timer.Start();
                this.otherCamera.Core.DisplayVideoParameters = true;
                this.otherCamera.Core.VideoDrawMode = VideoDrawMode.ScaleToFill;
                this.otherCamera.Core.ConnectEnded += DynamicCameraConnector_ConnectEnded;
                this.otherCamera.Core.Disconnected += DynamicCameraConnector_Disconnected;
                this.microphoneConnector.ConnectEnded += MicrophoneConnector_ConnectEnded;
                this.microphoneConnector.Disconnected += MicrophoneConnector_Disconnected;
                this.otherCamera.BeginConnect(this.DestID);
                this.microphoneConnector.BeginConnect(this.DestID);
            });
        }

(5)對於發起方,當收到對方同意的回覆後,也立即調用DynamicCameraConnector和MicrophoneConnector的Connect方法,連接到接收方的攝像頭、麥克風。

(6)當一方點擊掛斷的按鈕時,就會發送InformationTypes.CloseVideo類型的信息給對方,並調用DynamicCameraConnector和MicrophoneConnector的Disconnect方法斷開到對方設備的連接。

(7)另一方接收到InformationTypes.CloseVideo類型的信息時,也會調用DynamicCameraConnector和MicrophoneConnector的Disconnect方法以斷開連接。

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            this.otherCamera?.Disconnect();
            this.otherCamera?.Dispose();

            this.microphoneConnector?.Disconnect();
            this.microphoneConnector?.Dispose();

            this.selfCamera?.Disconnect();
            this.selfCamera?.Dispose();
        }

(8)如果接收到自己掉線的事件或好友掉線的事件,也採用類似掛斷對話的處理。 

四.下載

    Avalonia 版本即時通訊源碼: IM_VideoChat.Avalonia.rar

該源碼中包括如下項目:

(1)Oraycn.Demos.VideoChat.LinuxServer :     該Demo的Linux服務端(基於.NetCore)。

(2)Oraycn.Demos.VideoChat.ClientAvalonia :   該Demo的 Avalonia 客戶端。

          注: Linux客戶端內置的是x86/x64非託管so庫,若需要其它架構的so,請聯繫我們免費獲取。  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章