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)来查看这些信息。

三.源码下载

该Demo已经整合到入门Demo中了,请参见 ESFramework入门Demo

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

 下载免费版本的ESFramework 以及 demo源码  

Q Q:168757008

官网:www.oraycn.com

导航

首页

官方网站

立即咨询 

站内搜索

ESFramework 通信框架

价目表

详细说明

SDK与Demo下载

ESFramework FAQ

版本变更记录

OMCS 语音视频框架

价目表

详细说明

SDK与Demo下载

OMCS FAQ

版本变更记录

OrayTalk 企业即时通讯系统

价目表

详细说明

客户端下载

傲瑞实用组件

价目表

SDK下载

NPush 消息推送组件

StriveEngine 轻量级的通信引擎

MFile 语音视频录制组件

MCapture 语音视频采集组件

MPlayer 语音视频播放组件

OAUS 自动升级系统

傲瑞组件 FAQ

授权

授权流程

产品选购指南

授权方案说明

授权SDK使用说明

其它

SDK使用技巧

联系我们

电话:027-87638960

Q Q:168757008

邮件:master@oraycn.com