前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET+ Avalonia 实现跨平台的IM即时通讯、语音视频通话

.NET+ Avalonia 实现跨平台的IM即时通讯、语音视频通话

作者头像
郑子铭
发布2023-11-27 12:49:58
4460
发布2023-11-27 12:49:58
举报

前言

在 Avalonia 如火如荼的现在,之前使用CPF实现的简单IM,非常有必要基于 Avalonia 来实现了。Avalonia 在跨平台上的表现非常出色,对信创国产操作系统(像银河麒麟、统信UOS、Deepin等)也很不错。

现在,我们就来使用 Avalonia 实现一个跨平台的简单IM,除了文字聊天外,还可以语音视频通话。废话不多说,我们开始吧!

下图是这个简单IM的Avalonia客户端在国产统信UOS上的运行的截图:

一、IM 即时通讯系统主要功能

这个简单的IM系统实现了以下功能:

1、基础功能、文字聊天

客户端用户上下线时,通知其他在线用户。

当客户端与服务端网络断开时,进行自动重连,当网络恢复后,重连成功。

所有在线用户之间可以进行文字聊天(支持表情,支持撤回消息、删除消息)。

文件传送。

2、语音视频聊天、远程桌面

一方发起视频对话请求,对方同意后,即可开始视频对话。

在对话的过程中,任何一方都可以挂断,以终止对话。

在对话的过程中,任何一方掉线,都会自动终止对话。

双击视频窗口,会全屏显示视频,按esc退出全屏。

远程桌面或远程协助功能,也是跟视频聊天同样的流程,不再赘述。

二、开发环境

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

若要实现上述功能列表中列出来的所有功能,我们先要定义相应的通信消息的消息类型,如下所示:

代码语言:javascript
复制
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。

代码语言:javascript
复制
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方法,来处理收到的聊天信息和振动提醒。

代码语言:javascript
复制
void HandleInformation(string sourceUserID, int informationType, byte[] info);

服务端的CustomizeHandler实现了服务端的ICustomizeHandler接口,其主要实现HandleQuery方法来处理来自客户端的同步调用(InformationTypes.ClientCallServer)。

代码语言:javascript
复制
byte[] HandleQuery(string sourceUserID, int informationType, byte[] info);
4、服务端验证用户登录的帐号

服务端的BasicHandler类实现IBasicHandler接口,以验证登录用户的账号密码。

代码语言:javascript
复制
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”,分别演示了两种发送消息给对方的方式:

直接发给对方。(若P2P通道存在,则经由P2P通道发送)

代码语言:javascript
复制
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发送出去。

先发给服务器,再由服务器转发给对方。

具体实现,大家去参看源码,这里就不再赘述了。

6、客户端实现语音视频通话功能

语音视频通话实际运行起来后的效果如下所示:

我们先简单描述一下实现视频对话流程的要点,更详细的细节请查阅源代码。

1、发起方发送InformationTypes.VideoRequest类型的信息给对方,以请求视频对话。

程序中是在 VideoChatWindow 窗口显示的时候,来做这件事的:

代码语言:javascript
复制
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方法,连接到对方的摄像头、麦克风。

代码语言:javascript
复制
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方法以断开连接。

代码语言:javascript
复制
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 版本即时通讯源码

https://www.oraycn.com/DownLoadFiles/OMCS/IM_VideoChat.Avalonia.rar

该源码中包括如下项目:

1、Oraycn.Demos.VideoChat.LinuxServer

该Demo的Linux服务端(基于.NetCore)。

2、Oraycn.Demos.VideoChat.ClientAvalonia

该Demo的 Avalonia 客户端。

注:Linux客户端内置的是x86/x64非托管so库,若需要其它架构的so,请联系我们免费获取。

推荐阅读:

.NET 8来了,开发一套基于.NET 8的快速开发框架吧,就叫Simple

.NET 8 中都有哪些新的变化?

.NET NativeAOT 实现用户体验升级

推荐一个强大高效的 .NET 开源权限管理库

.NET8 正式发布, C#12 新变化

.NET 8 正式发布有那些新功能?

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-26,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、IM 即时通讯系统主要功能
  • 1、开发工具
    • 4、服务端验证用户登录的帐号
    相关产品与服务
    实时音视频
    实时音视频(Tencent RTC)基于腾讯21年来在网络与音视频技术上的深度积累,以多人音视频通话和低延时互动直播两大场景化方案,通过腾讯云服务向开发者开放,致力于帮助开发者快速搭建低成本、低延时、高品质的音视频互动解决方案。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    http://www.vxiaotou.com