现在我们将在ESFramework Demo -- 文件传送Demo 的基础上,使用ESPlus提供的第四个武器,为其增加P2P通信的功能。在阅读本文之前,请务必先掌握ESFramework 开发手册(04) -- 可靠的P2P 一文中介绍的P2P的基础知识以及相关API的用法。

本Demo主要演示以下功能:

(1)创建基于TCP的P2P通道

(2)创建基于UDP的P2P通道(内部使用可靠的UDP)

(3)使用P2P通道发送消息和传送文件

一.服务端

在P2P打洞的过程中,服务端会参与协助P2P通道的建立,整个过程是由ESFramework/ESPlus内部自动完成的,而这个过程对于框架使用者是透明的。P2P通道创建后,客户端与客户端之间的通信就与服务器没有任何关系了。所以我们直接把上一个demo的服务端拿过来用,不需要做任何修改。

二.客户端

客户端主要使用IRapidPassiveEngine提供的P2PController来查询和控制P2P通道的状态。

尝试创建P2P通道

正如ESFramework 开发手册(04) -- 可靠的P2P 一文中介绍的,并不是所有的客户端之间的P2P通道都可以创建成功,创建P2P通道是一个尝试的过程,IP2PController的P2PConnectAsyn方法就是尝试与目标用户创建P2P通道。

时机很重要。在何时创建P2P通道了?一般而言,是在两个客户端需要高频通信之前,调用P2PConnectAsyn进行尝试创建。

在本Demo中,我们是在每次打开与目标用户的聊天窗口的时候,来尝试创建P2P通道的。如下所示:

  void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (e.Button != System.Windows.Forms.MouseButtons.Left)
{
return;
} ListViewHitTestInfo info = this.listView1.HitTest(e.Location);
if (info.Item != null)
{
//尝试与目标用户建立P2P通道
this.rapidPassiveEngine.P2PController.P2PConnectAsyn(info.Item.Text); ChatForm form = this.chatFormManager.GetForm(info.Item.Text);
           ......
       }
  }

使用P2PConnectAsyn方法开始打洞时,若双方位于同一局域网,一般会建立起基于TCP的P2P通道;若双方位于不同的网络,一般会建立起基于UDP的P2P的通道。如果与目标用户之间已经存在可用的P2P通道,则P2PConnectAsyn将不再做任何动作,而直接返回。

为了获得P2P通道创建成功或失败以及后续P2P通道被关闭的通知,demo中我们在MainForm的Initialize方法中预定了P2PController的P2PChannelOpened和P2PChannelClosed事件。

   //预定P2P Channel创建成功的事件
this.rapidPassiveEngine.P2PController.P2PChannelOpened += new CbGeneric<P2PChannelState>(P2PController_P2PChannelOpened);
//预定P2P Channel关闭时的事件
this.rapidPassiveEngine.P2PController.P2PChannelClosed += new CbGeneric<P2PChannelState>(P2PController_P2PChannelClosed);

当P2P通道创建成功或被关闭时,本demo通过修改对应聊天窗口的Title文字来显示这种状态。比如,当P2P通道创建成功时,聊天窗口的Title显示如下:

通常,如果两个客户端位于同一个LAN,或者有一个客户端直接位于Internet上,则它们之间的P2P通道是基于TCP的;否则,创建的P2P通道是基于UDP的。

ChatForm提供了ShowP2PChannelState方法来显示与聊天对象之间的P2P通道状态。

       ///<summary>
/// 显示P2P连接的状态
///</summary>
public void ShowP2PChannelState(P2PChannelState state)
{
this.Text = (state != null) ? string.Format("正在与{0}对话中【{1}直连:{2}】...", this.friendID, state.ProtocolType, state.DestIPE) : string.Format("正在与{0}对话中...", this.friendID);
}

请注意,当与目标用户之间没有P2P通道时,P2PController的GetP2PChannelState方法返回的是null。

观察P2P通信

当P2P通道创建成功后,两个用户之间的后续通信将经过P2P通道传送,在本Demo中,表示后续的聊天消息以及文件传送都将通过P2P通道进行。

那么,如何判断消息是通过服务器中转的,还是经过P2P通道直接传送的了?我们常用的有两个简单的方法。

(1)观察服务器的MainServerForm界面。

如果消息是经过服务器中转的,那么界面上显示消息接收者用户对应的“下载次数”、“上传次数”、“最后一次下载时间”等都会跟着发生变化。就本例来说,每当你给对方发送一个聊天消息,如果是经过服务器中转,那么界面上显示的对方的下载次数会增加1,自己的上传次数也增加1,自己的最后一次上传时间也会变化。而如果消息是通过P2P通道传送的,这些数据就不会受影响。

(2)查看资源监视器

如果是Win7的系统,任务管理器“性能”显示中提供了“资源监视器”,可以监控网络的活动。使用它,我们就可以看到应用程序在和哪些机器进行通信。如下图所示:

上面是我们另一个P2P应用demo的截图,图中59.175.145.163是服务器的IP,而我们看到OMCS.ClientDemo.exe接收数据的主要流量来自于ZY-PC这台电脑,这表示两个客户端之间的数据是经过P2P通道传送的,没有通过服务器中转。之所以图中显示的客户端与服务器之间还有微小的流量,那是由类似定时心跳消息等产生的。

如果不是Win7系统,也可以通过安装网络监控软件(如NetLimiter)来查看这些信息。

三.源码下载

ESFramework.Demos.P2P 源码

阅读 更多ESFramework开发手册系列文章

-----------------------------------------------------------------------------------------------------------------------------------------------

关于ESFramework的任何问题,欢迎联系我们:

电话:027-87638960

Q Q:372841921

ESFramework Demo -- P2P通信Demo(附源码)的更多相关文章

  1. Qt一步一步实现插件通信(附源码)

      前一章已经实现了主程序调用加载插件功能,这一章描述主程序和插件间通信功能 说道Qt的通信必须要了解信号和槽的机制原理,这里不做论述,不清楚的同学去看看信号和槽机制 不废话直接上步骤,在上一章的基础 ...

  2. 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)

    在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...

  3. 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)

    在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前d ...

  4. C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)

    前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...

  5. 聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)

    本文我们将介绍在ESFramework 4.0 快速上手(08) -- 入门Demo,一个简单的IM系统(附源码)的基础上,增加文件传送的功能.如果不了解如何使用ESFramework提供的文件传送功 ...

  6. 微服务8:通信之RPC实践篇(附源码)

    ★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...

  7. C#编程总结(七)数据加密——附源码

    C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容 ...

  8. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  9. wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)

    原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依 ...

  10. ASP.NET程序读取二代身份证(附源码)

    原文:ASP.NET程序读取二代身份证(附源码) 一般来说winform应用程序解决这个问题起来时很容易的,web应用程序就麻烦一点了. 这里我说说我的解决思路: 一.你必要有联机型居民身份证阅读器一 ...

随机推荐

  1. 双向数据绑定---AngularJS的基本原理学习

    Angular JS (Angular.JS) 是一组用来开发Web页面的框架.模板以及数据绑定和丰富UI组件.它支持整个开发进程,提供web应用的架构,无需进行手工DOM操作. AngularJS非 ...

  2. jquery文档处理如after错误

    $('.foo').after('<li>0<li>')会添加两个元素 $('.foo').after('<li>o</li>')只会添加一个元素 所以 ...

  3. Python中strip方法的妙用

    [开胃小菜] 当提到python中strip方法,想必凡接触过python的同行都知道它主要用来切除空格.有下面两种方法来实现. 方法一:用内置函数 #<python> if __name ...

  4. cacti 安装和组件添加

    安装cacti 步骤 1.准备lamp环境 2.准备所需包:rrdtool(绘图) cacti(安装程序) net-snmpd(数据收集) 3.安装所需库文件 rrdtool所需库文件有: cairo ...

  5. 【Atheros】禁用CSMA之后pktgen发包一分钟后无法发送的问题

    无线网络中各个节点不断地广播信标帧,收到某节点的信标帧之后才知道这个节点存在,知道它的网络配置是怎么样的,才能知道应该怎么和它通信. 那么问题来了,禁用了CSMA之后,发送节点全力发送,那么它会永远占 ...

  6. Awesome Vue.js vue.js学习资源链接大全 中文

    https://blog.csdn.net/caijunfen/article/details/78216868

  7. redis启动错误-- Creating Server TCP listening socket *:6379: listen: UnKnown error

    前提:windows server 2008.redis 3.x 今天给服务器部署redis环境,文件配置.服务安装都很顺利,可就在启动服务的时候提示 百度老半天也没找到个说到点子上的. 这里记录下解 ...

  8. Angular入门(四) Router 替换当前页面

    1.在 xx.html 中直接 写标签       <a [routerLink]="['/home']">home</a>   2.在 xx.html 中 ...

  9. JavaScript中实现继承

    今天即兴研究了下JS,查阅了相关资料 ,发现Js中没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(i ...

  10. sed命令使用举例

    选择操作的行范围 sed -n '1,2p' testsed2.txt  匹配第1到2行 sed -n '/a/,/b/p' testsed2.txt  匹配从包含a的行到包含b的行 sed -n ' ...