GGTalk 开源即时通讯系统源码剖析之:远程磁盘 (低调赠送GGTalk最新源码)

继上篇《GGTalk 开源即时通讯系统源码剖析之:聊天消息防错漏机制》介绍了 GGTalk 对消息的可靠性,即消息的不丢失和不重复做了一系列优化处理,以保证不会错漏消息。这篇我们来剖析 GGTalk 新增的远程磁盘功能其对应的源码实现。

在之前的博文《实现远程磁盘:像访问自己的电脑硬盘一样访问对方的电脑硬盘 》,我们通过一个Demo介绍了访问远程磁盘如何实现。最近,我们已经在GGTalk开源即时通讯IM的最新版中增加访问好友磁盘的功能:在一对一的对话窗口,请求方可以发起访问对方磁盘的请求,如果对方同意,则请求方就可以通过远程磁盘的窗口来操作对方的磁盘了。现在我们来看看GGTalk的远程磁盘这一功能具体是如何实现的,大家可以先下载GGTalk的最新源码,然后对照源码,更容易理解本文的内容。

一. 定义消息协议

在远程磁盘请求方和应答方相互通信之前,我们先定义好远程磁盘这一功能需要用到的消息协议。

复制代码
/// <summary>
/// 交互媒体的类型。
/// </summary>
public enum CommunicateMediaType
{
    Video = 0,
    Audio,
    RemoteHelp,
    RemoteControl,
    RemoteDisk,
    GroupVideo
}

在交互媒体的类型枚举上,我们增加了 远程磁盘(RemoteDisk)这个类型。

再结合原先的 CommunicateType 枚举,我们就可以组合出远程磁盘相关的业务通信:请求、应答(同意或拒绝)、中断等。

复制代码
/// <summary>
/// 交互的类型。比如 请求视频会话,同意视频会话,拒绝视频会话,终止视频会话
/// </summary>
public enum CommunicateType
{
    Request = 0,
    Agree,
    Reject,
    Terminate,
    Busy
}

有了上面的铺垫,我们就可以来实现整个远程磁盘功能的业务流程了。

二. 远程磁盘请求方实现

首先,使用VS 2022 打开 GGTalk 解决方案,找到GGTalk 客户端项目(Windows版):

我们在一对一的聊天窗口 FriendChatForm (在Forms文件夹下)上增加"请求访问对方磁盘"的按钮,如下图所示:

点击该按钮时,将执行如下动作:

复制代码
public void RequestControlFriendDisk()
{
    //如果自己掉线,则直接返回。
    if (this.resourceCenter.ClientGlobalCache.CurrentUser.UserStatus == UserStatus.OffLine)
    {
        return;
    }           

    this.resourceCenter.ClientOutter.SendMediaCommunicate(this.currentFriend.ID, CommunicateMediaType.RemoteDisk, CommunicateType.Request, null);
    NDiskOutter diskOutter = new NDiskOutter(this.resourceCenter.RapidPassiveEngine, this.resourceCenter.NDiskPassiveHandler);            
    this.remoteDiskForm = new RemoteDiskForm(this.currentFriend.ID,ClientType.DotNET,this.currentFriend.DisplayName, diskOutter, this.resourceCenter.RapidPassiveEngine.FileOutter, this.resourceCenter.CurrentUserID);
    this.remoteDiskForm.RemoteDiskRequestCancelled += new CbGeneric(remoteDiskForm_RemoteDiskRequestCancelled);
    this.remoteDiskForm.RemoteDiskEnded += new CbGeneric<bool>(remoteDiskForm_RemoteDiskEnded);
    this.remoteDiskForm.Show();
}

(1)客户端通过调用 IClientOutter 的 SendMediaCommunicate 方法,来实现与远程磁盘功能相关的业务通信。

(2)通过 CommunicateMediaType.RemoteDisk 和 CommunicateType.Request 来表名这次交互发送的是一个远程磁盘请求。

(3)在等待对方应答期间,使用 RemoteDiskForm 来显示正在等待对方回复。如下图所示:

(4)如果对方同意了远程磁盘请求,那么RemoteDiskForm 将改变状态,请求方就能通过该窗体来操作对方的磁盘,如下图所示:

关于 RemoteDiskForm 的具体实现细节,可以参考 《实现远程磁盘:像访问自己的电脑硬盘一样访问对方的电脑硬盘 》。

三. 远程磁盘应答方实现

当应答方收到跟远程磁盘相关的业务消息时,会进入到 RemoteDiskManager的 HandleRemoteDisk 方法,如下代码所示:

复制代码
public void HandleRemoteDisk(CommunicateType communicateType, string tag)
{
    if (communicateType == CommunicateType.Request)
    {
        this.OnRemoteDiskRequestReceived();
        this.ownerForm.FlashWindow();
        return;
    }

    if (communicateType == CommunicateType.Agree)
    {
        this.OnRemoteDiskAnswerReceived(true);
        this.ownerForm.FlashWindow();
        return;
    }

    if (communicateType == CommunicateType.Reject)
    {
        this.OnRemoteDiskAnswerReceived(false);
        this.ownerForm.FlashWindow();
        return;
    }

    if (communicateType == CommunicateType.Terminate)
    {
        if (tag == "owner")
        {
            this.OnOwnerTerminateRemoteDisk();
        }
        else
        {
            this.OnGuestCloseRemoteDisk();
        }
        this.ownerForm.FlashWindow();
        return;
    }    
}

(1)在 OnRemoteDiskRequestReceived 方法中,会在窗体的右侧,显示远程磁盘请求,如下截图:

(2)当应答方点击"接受"或"拒绝"按钮时,也将通过调用 IClientOutter 的 SendMediaCommunicate 方法(位于RemoteDiskManager类),来将回复消息发送给请求方。

复制代码
void remoteDiskRequestPanel_RemoteRequestAnswerd(bool agree)
{
    this.ownerForm.RemoveDisplayedPanel(this.Title_Disk);    
    this.resourceCenter.ClientOutter.SendMediaCommunicate(this.currentFriend.ID, CommunicateMediaType.RemoteDisk, agree ? CommunicateType.Agree : CommunicateType.Reject, null);
    string showText = string.Format("您{0}了对方的磁盘访问请求。", agree ? "同意" : "拒绝");
    this.ownerForm.AppendSysMessage(showText);

    if (agree)
    {
        this.remoteDiskHandlePanel.OnAgree();
        this.ownerForm.AddDisplayedPanel(this.Title_Disk, this.remoteDiskHandlePanel);
    }
}

(3)如果点击"接受"按钮,则聊天窗体右侧将会出现"远程磁盘的控制面板",以随时可以收回远程磁盘控制权。

(4)在对方控制自己磁盘的过程中,应答方点击上方的"终止"按钮,即可结束控制。这是给对方发送一个"终止控制"的 CommunicateType.Terminate 消息:

复制代码
void remoteDiskHandlePanel_RemoteDiskTerminated()
{
    this.ownerForm.RemoveDisplayedPanel(this.Title_Disk);
    this.resourceCenter.ClientOutter.SendMediaCommunicate(this.currentFriend.ID, CommunicateMediaType.RemoteDisk, CommunicateType.Terminate, "owner");
    string showText = "您关闭了磁盘共享。";
    this.ownerForm.AppendSysMessage(showText);
}

四. 结语

以上就是关于 GGTalk 远程磁盘功能的设计与实现的核心了。在某些办公场景中,远程磁盘这个功能还是很有用的,所以,GGTalk 即时通讯就实现该功能,方便那些有需要的人。

如果你觉得还不错,请点赞支持啊!下篇再见!

若需下载GGTalk最新源码,请移不到 GGTalk 源码下载中心 ,谢谢 。

相关推荐
jeff聊企业数字化2 天前
私有化即时通讯选型指南:兼顾安全与高效
go·业界资讯·即时通讯
恒拓高科WorkPlus2 天前
BeeWorks 私有化安全协作平台白皮书(2026 版)
即时通讯·白皮书·协作平台·协作平台白皮书·即时通讯白皮书
恒拓高科WorkPlus7 天前
团队协作和即时通讯一体化的软件,目前哪个用户体验最好?
即时通讯·私有化的企业 im·企业 im
恒拓高科WorkPlus9 天前
信创即时通讯怎么选?BeeWorks 的全栈适配与安全实践
即时通讯·信创即时通讯
恒拓高科WorkPlus10 天前
私有化视频会议怎么选?BeeWorks Meet 的安全与高效之道
私有化部署·即时通讯·视频会议
hellojackjiang201112 天前
社交场景下的统一即时通讯im消息流交互层模块化技术实践
即时通讯·im开发·架构设计
zhuweisky24 天前
去中心化的内网聊天软件Lachat是如何实现的?
即时通讯·聊天软件·信创国产·内网聊天·局域网聊天
hellojackjiang20112 个月前
鸿蒙Next原生IM即时通讯RainbowTalk,纯ArkTS编写,基于开源MobileIMSDK框架
网络编程·信息与通信·harmonyos·即时通讯
CherishXt3 个月前
对接腾讯IM,实现个人业务系统页面按钮直接跳转到和用户的聊天页面(不需要加好友)
uniapp·即时通讯·im
hellojackjiang20113 个月前
如何保障分布式IM聊天系统的消息有序性(即消息不乱)
分布式·架构·即时通讯·im开发