实现远程磁盘:像访问自己的电脑硬盘一样访问对方的电脑硬盘 (附Demo源码)
在现实场景中,远程桌面的功能大家已经用得很多了,而在某些场景下,我们需要使用类似的远程磁盘功能,这样能非常方便地操作对方电脑磁盘的目录、以及传送文件。那么,这样的远程磁盘功能要怎么实现了?
这次我们将给出一个完整的Demo来演示远程磁盘要怎么实现,同时,这个Demo也给出了个人网盘是如何实现的。个人网盘可以看做是远程磁盘应用的一个特例,即,个人网盘就是访问服务器上的一个特定文件夹。废话不多说,先上图看看这个远程磁盘Demo的基本功能。
一. 远程磁盘功能展示
打开到对方的远程磁盘后,我们就可以看到对方电脑的硬盘了,点击任何一个,就可以访问该盘下面的文件。

双击文件,就可以下载文件到本地;右键菜单则可以上传本地文件到远程磁盘。

二. 远程磁盘代码实现
在实现远程磁盘时,我们分为两个层面介绍,一个是底层业务通信层面,另一个是上层的UI展现层面。
1. 底层业务通信实现
比如,当我们使用远程磁盘功能时,最常见的就是去获取对方电脑某个目录下的所有文件及文件夹,那么,这个功能是怎么实现的了?
基于ESFramework,实现这点其实很简单,我们举例说明。以A用户作为磁盘的分享者,B用户作为远程磁盘的访问者,A和B都启动了该Demo的客户端并登录。此时,B要访问A用户电脑上某个目录下的文件列表,那么,B就可以给A发一个请求消息,并得到回复,如下所示(NDiskOutter 类的 GetSharedDirectory 方法):
/// <summary>
/// 获取目标用户电脑上指定目录下的文件列表信息。
/// </summary>
/// <param name="ownerID">目标用户的账号(磁盘分享者)</param>
/// <param name="clientType">目标用户的设备类型</param>
/// <param name="netDiskID">网盘的标志。(对于远程磁盘而言,即OwnerID为某个用户的ID时,该参数可传null)。如果是群组共享的文件夹,则可以将其设置为对应的群组的ID。</param>
/// <param name="dirPath">指定目录的路径</param>
/// <returns>目录下的文件列表信息</returns>
public SharedDirectory GetSharedDirectory(string ownerID,ClientType clientType,string netDiskID ,string dirPath)
{
ReqDirectoryContract contract = new ReqDirectoryContract(netDiskID, dirPath);
byte[] res;
if (!ownerID.Equals(NetServer.SystemUserID)) //远程磁盘
{
res = this.p2pQueryOutter.Query(ownerID, clientType, this.fileDirectoryInfoTypes.ReqDirectory, CompactPropertySerializer.Default.Serialize<ReqDirectoryContract>(contract), "");
}
else //网盘
{
res = this.customizeOutter.Query(this.fileDirectoryInfoTypes.ReqDirectory, CompactPropertySerializer.Default.Serialize<ReqDirectoryContract>(contract));
}
ResDirectoryContract resContract = CompactPropertySerializer.Default.Deserialize<ResDirectoryContract>(res, 0);
return resContract.SharedDirectory;
}
无论是网盘,还是远程磁盘,都可以通过上述的代码来进行调用,以获取对方电脑指定目录下的文件列表。
(1)特别注意,上述代码中红色字体突出显示的Query方法,该方法的含义是:向对方(或服务器)发送 ReqDirectory 请求,并返回对方的应答结果。
(2)返回的 SharedDirectory 对象,里面包含了目录下的文件列表和子文件夹列表,可以通过 FileList 和 SubDirectorys 属性获取。
那么,A作为分享方,是如何处理来自B的 ReqDirectory 请求的了?
我们来看看 NDiskPassiveHandler 类的 HandleQuery 方法中对 ReqDirectory 请求的处理:
if (informationType == this.fileDirectoryInfoTypes.ReqDirectory)
{
ReqDirectoryContract contract = CompactPropertySerializer.Default.Deserialize<ReqDirectoryContract>(info, 0);
string fullPath = this.ConstructFullPath(contract.DirectoryPath);
SharedDirectory dir = SharedDirectory.GetSharedDirectory(fullPath);
return CompactPropertySerializer.Default.Serialize<ResDirectoryContract>(new ResDirectoryContract(dir));
}
(1)首先,将二进制请求消息反序列化为 ReqDirectoryContract 对象,从中拿到对方想要请求的目录路径。
(2)通过 SharedDirectory 的静态方法 GetSharedDirectory 获取目标目录下的文件列表和子文件夹列表,并包装成 SharedDirectory 对象。
(3)将 SharedDirectory 对象序列化成二进制后,返回给请求方。
上面就以请求指定目录下的文件列表及文件夹列表为例,说明了底层业务通信的过程。其它的业务通信就不再赘述了,大家可自行查看源码。
2. UI 实现
在客户端,最主要的UI控件就是 NDiskBrowser 的实现,它的功能主要有:
(1)浏览远程磁盘下的目录及文件。
(2)可从远程磁盘下载文件到本地电脑。
(3)可将本地文件上传到远程磁盘。
我们仍然以浏览远程磁盘指定目录下的所有文件及文件夹为例,来看看 NDiskBrowser 是如何在UI展现的。
SharedDirectory sharedDirectory = this.nDiskOutter.GetSharedDirectory(this.ownerID, this.clientType, this.netDiskID , path); foreach (DirectoryDetail dirDetail in sharedDirectory.SubDirectorys)
{
ListViewItem item = new ListViewItem(new string[] { dirDetail.Name, dirDetail.CreateTime.ToString(), "" }, 0);
item.Tag = new FileOrDirectoryTag(dirDetail.Name, 0, dirDetail.CreateTime, false);
this.listView_fileDirectory.Items.Add(item);
} foreach (FileDetail file in sharedDirectory.FileList)
{
ListViewItem item = new ListViewItem(new string[] { file.Name, file.CreateTime.ToString(), PublicHelper.GetSizeString((uint)file.Size) }, this.GetIconIndex(file.Name));
item.Tag = new FileOrDirectoryTag(file.Name, file.Size, file.CreateTime, true);
item.ToolTipText = string.Format("大 小:{0}\n创建日期:{1}", PublicHelper.GetSizeString((uint)file.Size), file.CreateTime);
this.listView_fileDirectory.Items.Add(item);
}
在通过 NDiskOutter 的 GetSharedDirectory 方法拿到 SharedDirectory 对象后,就将其 SubDirectorys 所包含的每个子文件夹作为 ListViewItem 添加到 ListView 中显示出来;同时,也将其 FileList 所包含的每个文件作为 ListViewItem 添加到 ListView 中显示出来。这样就出现了我们之前截图的效果。
NDiskBrowser 的实现代码虽然比较多,但是都很简单,大家下载源码后可自行查看。
三. Demo下载及运行
1. Demo 源码下载:Oraycn.RemoteDisk.rar
2. 运行Demo
(1)运行服务端。
双击服务端运行目录下的 Oraycn.RemoteDisk.Server.exe ,即可启动服务端,如下截图所示:

(2)运行客户端。
修改客户端配置文件 Oraycn.RemoteDisk.exe.config 中的 ServerIP 为运行服务端电脑的 IP地址,然后双击 Oraycn.RemoteDisk.exe 启动客户端:

账号密码随便填,登录成功后,进入主界面:

此时,在主界面的输入框中填上对方的账号,点击“访问他的磁盘”按钮,如果对方在线,就会弹出此文第一张截图的窗体了。
如此,我们就可以完全的操控远程磁盘了。
接下来,我们将在 GGTalk 开源即时通讯系统 中,加上远程磁盘的功能,敬请期待!
实现远程磁盘:像访问自己的电脑硬盘一样访问对方的电脑硬盘 (附Demo源码)的更多相关文章
- yii2获取登录前的页面url地址--电脑和微信浏览器上的实现以及yii2相关源码的学习
对于一个有登录限制(权限限制)的网站,用户输入身份验证信息以后,验证成功后跳转到登录前的页面是一项很人性化的功能.那么获取登录前的页面地址就很关键,今天在做一个yii2项目的登录调试时发现了一些很有意 ...
- 可在广域网部署运行的QQ高仿版 -- GG叽叽V2.0,增加网盘和远程磁盘功能(源码)
尽力2~3周发布一个版本,我这次也没有失言.这段时间内,我仿照QQ的微云功能,在GG中增加了网盘的功能,而且,我还自创了一个QQ没有的新的功能:远程磁盘.正如远程桌面一样,远程磁盘允许我们像访问本地磁 ...
- PHP判断访问终端,电脑或手机访问
函数代码: //判断电脑或手机访问 function is_mobile(){ $user_agent = $_SERVER['HTTP_USER_AGENT']; $mobile_agents = ...
- tomcat发布项目时,localhost可以访问,用ip地址不能访问,同时其他电脑也不能访问。
最近在开发项目中,遇到的一个问题是:在 tomcat中发布一个web项目,但是发布成功后,只能用http://localhost:8080/aml访问项目,不能用http://172.0.0.1:80 ...
- vue配置手机通过IP访问,Win10让局域网内其他电脑通过IP访问网站的方法
vue配置手机通过IP访问config/index.js// Various Dev Server settings host: '0.0.0.0', // can be overwritten by ...
- dedecms网站扩展手机网站—共用数据库真正做到电脑手机同步访问,原pc站无需改动,对原pc站无任何影响
在如今无线互联网大潮的冲击下,越来越多的pc网站访问量下降,首当其冲的就是以pc网站为生的站长们,为了顺应无线互联网的要求,站长们很有必要为自己的pc网站扩展一套手机网站,更早的抓住手机用户的流量,使 ...
- .net网站上传图片换电脑不显示 当不用网站的IP地址访问图片,只用相对路径访问时,在发布网站的时候,将上传图片的目标文件夹,包含在项目中再发布即可。
.net网站上传图片换电脑不显示 当不用网站的IP地址访问图片,只用相对路径访问时,在发布网站的时候,将上传图片的目标文件夹,包含在项目中再发布即可.
- Win10系统下怎么让局域网内其他电脑通过IP访问网站
最近,有位win10系统用户在电脑上制作好网站后,希望能让局域网内的其他电脑通过IP直接访问自己电脑的网站,以便得到更好地测试效果.可是,该用户操作了很久都没成功.那么,我们如何配置win10电脑的I ...
- ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载
第八章是一个非常重要的章节,讲述的是实模式下对硬件的访问(这一节主要讲的是硬盘),还有用户程序重定位的问题.现在整理出来刚好能和保护模式下的用户程序定位作一个对比. ★PART1:用户程序的重 ...
- Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试
摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...
随机推荐
- 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体的替代品,可本地部署+知识库,注册即可有750w的token使用
最近火山引擎推出了自家联网版的DeepSeekR1,并且加入了联网的功能,不用担心DeepSeek本体的服务器繁忙了,可以说直接是DeepSeek本体的替代品.现在注册即送30块体验价(相当于750w ...
- @SpringBootApplication自动配置原理
@EnableAutoConfiguration 是核心,他会调用一个@Import注解.我们已知Import自动配置得实现是通过创建ImportSelector 接口的实现类并重写里面selectI ...
- 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
效果 来具体介绍之前先来看看效果. 使用C#构建了一个简单的MCP客户端,以下为运行这个简单客户端的截图,同样可以在Cline等其它的一些MCP客户端中玩耍. 创建一个数据库表: 获取数据库中的所有表 ...
- U盘制作、安装Ubuntu系统
制作 ubuntu U盘启动盘 下载Ubuntu镜像 打开 Ubuntu 官网:https://ubuntu.com/download/desktop ,进入页面后,点击右边的[Download]按钮 ...
- mac mamp php扩展安装
官网下载需要开启的php扩展 PHP扩展下载官网地址 解压扩展包,指定mamp所使用的php版本的phpize编译安装 # 在解压的扩展包中执行以下命令 /Applications/MAMP/bin/ ...
- Go语言中的匿名函数和闭包,简单理解
匿名函数是一种没有函数名的函数,即定义即使用:闭包作为一种携带状态的函数,我们可以简单地将它理解为"对象",因为它同时具备状态和行为. 匿名函数 匿名函数没有函数名,只有函数体,它 ...
- Pandas中的选择
1.选择 更多细节可见官方文档 import pandas as pd ID = [1,2,3] Name = ['Student_001','Student_002','Student_003'] ...
- Windows Terminal
... Windows Terminal 安装 命令行接口 Windows Terminal 的命令行接口是 wt 因此我们可以在运行输入 wt 打开 Windows Terminal 也可以在资源管 ...
- git 访问方式浅谈
小小总结下git的访问方式,留爪. git访问方式简介 https:每次fetch/push/pull都需要输入username & password ssh:通过ssh-keygen生成的公 ...
- Debian 9 更换源
Debian 全球镜像站 # 先备份源列表文件 mv /etc/apt/sources.list /etc/apt/sources.list.bak # 生成新的源列表文件(用的国内源镜像) echo ...