ESFramework Demo -- P2P通信Demo(附源码)
现在我们将在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的任何问题,欢迎联系我们:
电话:027-87638960
Q Q:372841921
ESFramework Demo -- P2P通信Demo(附源码)的更多相关文章
- Qt一步一步实现插件通信(附源码)
前一章已经实现了主程序调用加载插件功能,这一章描述主程序和插件间通信功能 说道Qt的通信必须要了解信号和槽的机制原理,这里不做论述,不清楚的同学去看看信号和槽机制 不废话直接上步骤,在上一章的基础 ...
- 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)
在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...
- 聊天系统Demo,增加Silverlight客户端(附源码)-- ESFramework 4.0 快速上手(09)
在ESFramework 4.0 快速上手 -- 入门Demo,一个简单的IM系统(附源码)一文中,我们介绍了使用ESFramework的Rapid引擎开发的winform聊天程序,本文我们将在之前d ...
- C#轻量级通通讯组件StriveEngine —— C/S通信开源demo(2) —— 使用二进制协议 (附源码)
前段时间,有几个研究ESFramework通信框架的朋友对我说,ESFramework有点庞大,对于他们目前的项目来说有点“杀鸡用牛刀”的意思,因为他们的项目不需要文件传送.不需要P2P.不存在好友关 ...
- 聊天系统Demo,增加文件传送功能(附源码)-- ESFramework 4.0 快速上手(14)
本文我们将介绍在ESFramework 4.0 快速上手(08) -- 入门Demo,一个简单的IM系统(附源码)的基础上,增加文件传送的功能.如果不了解如何使用ESFramework提供的文件传送功 ...
- 微服务8:通信之RPC实践篇(附源码)
★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...
- C#编程总结(七)数据加密——附源码
C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容 ...
- Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...
- wpf 模拟3D效果(和手机浏览图片效果相似)(附源码)
原文 wpf 模拟3D效果(和手机浏览图片效果相似)(附源码) pf的3D是一个很有意思的东西,类似于ps的效果,类似于电影动画的效果,因为动画的效果,(对于3D基础的摄像机,光源,之类不介绍,对于依 ...
- ASP.NET程序读取二代身份证(附源码)
原文:ASP.NET程序读取二代身份证(附源码) 一般来说winform应用程序解决这个问题起来时很容易的,web应用程序就麻烦一点了. 这里我说说我的解决思路: 一.你必要有联机型居民身份证阅读器一 ...
随机推荐
- Bootstrap学习速查表(四) 栅格系统
Bootstrap框架的网格系统工作原理如下: 1.数据行(.row)必须包含在容器(.container)中,以便为其赋予合适的对齐方式和内距(padding).如: 2.在行(.row)中可以添加 ...
- jdk并发工具包之锁
1.cynchronized扩展:可重锁入ReentrantLock ReentrantLock是通过cas算法实现的 RenntrantLock lock=new ReentrantLock(); ...
- 数字证书中keytool命令使用说明
这个命令一般在JDK\jre\lib\security\目录下操作 keytool常用命令 -alias 产生别名 -keystore 指定密钥库的名称(就像数据库一样的证书库,可以 ...
- python学习(六)元组学习
元组就是列表的一种,不过元组具有不可变性,而且是用圆括号访问的. 索引(下表索引或者键索引都是用的中括号) #!/usr/bin/python # 这节来学习元组, tuple, 基本上就像一个不可以 ...
- eclipse如何debug调试jdk源码
java是一门开源的程序设计语言,喜欢研究源码的java开发者总会忍不住debug一下jdk源码.虽然官方的jdk自带了源码包src.zip,然而在debug时查看变量却十分麻烦.例如调试HashMa ...
- 【JavaSE】Java问题总结
使用BufferedInputStream时OutOfMemoryError异常 eclipse Luna安装subversion(SVN) 使用BufferedInputStream时OutOfMe ...
- 【C语言】一句printf代码——{ a[0] ? 0[a] }
这是前段时间做的http://fun.coolshell.cn/中的一道题,很有意思,涉及的其实是C的基础,不过当时第一次看见这行代码确实把我弄懵了: printf(&unix["\ ...
- 用Newtonsoft将json串转为对象的方法(详解)
首先,将json串转为一个JObject对象: JObject jo = (JObject)JsonConvert.DeserializeObject(CurrentSelectedItemReq) ...
- Easy AR简单教程
Easy AR简单教程 相关SDK资源下载链接:http://pan.baidu.com/s/1dERtCWD 密码:o0jd 1.ImageTarget的制作 (1).导入EasyARSD包,删 ...
- 【BZOJ1150】[CTSC2007]数据备份Backup 双向链表+堆(模拟费用流)
[BZOJ1150][CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此 ...