找回密码
 立即注册
首页 业界区 业界 利用WCF的P2P共享剪贴板上的数据

利用WCF的P2P共享剪贴板上的数据

胰芰 2025-5-29 15:19:52
WCF与P2P   
    WCF是用来实现数据通信的,这篇文章中。我将带领大家进入WCF的P2P的世界。通过一个实例,说明WCF中使用P2P。
    首先让我们了解一下什么是P2P。详细见:P2P。这里根据我的理解,结合WCF简单的叙述一下。一般使用WCF,客户端与客户端交互都要使用一个服务端作为中间站。客户端将数据传递给服务端,服务端再转发给其他的客户端。很明显,这显然加重了服务端的负担。P2P是解决这个问题的。每一个客户端既可以是接受数据的客户端,又是上传数据的服务端。用过PPS和迅雷的童鞋就能很容易的理解了,这两个软件既要上传数据,又要下载数据。看下面两幅图:
1.jpeg
 
图一:围绕中心服务器打转
2.jpeg
 
图二:P2P分布
实例的功能
    我实现的这个例子的功能是:在一个局域网内,有很多台电脑。当其中一台电脑实现了复制或者剪贴,在其他的电脑上将显示复制和剪贴的数据。你可以实现Ctrl+C或者Ctrl+X进行数据复制或者剪贴。在其他的电脑上有一个窗体专门显示你复制或者剪贴的数据(限定了文本数据)。
    实现这个程序有两个难点:
    1、如何监听Ctrl+C或者Ctrl+X等事件
    2、不需要特定的服务端(不通过WCF的双工通信),如果通过P2P去实现数据通信。
实例的实现:
    下面根据这两个难点来展开去实现。
   一、事件监听:
    1、在WindowsForm应用程序中,protected override void WndProc(ref System.Windows.Forms.Message m)方法可以供我们去重载来实现事件的监听。判断Message的编号,如果是复制或者剪贴事件。我们就去通过WCF的P2P服务来广播剪贴板中的信息。代码如下:
  1.         protected override void WndProc(ref System.Windows.Forms.Message m)
  2.         {
  3.             // defined in winuser.h
  4.             const int WM_DRAWCLIPBOARD = 0x308;
  5.             const int WM_CHANGECBCHAIN = 0x030D;
  6.             switch (m.Msg)
  7.             {
  8.                 case WM_DRAWCLIPBOARD:
  9.                     DisplayClipboardData();
  10.                     SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
  11.                     break;
  12.                 case WM_CHANGECBCHAIN:
  13.                     if (m.WParam == nextClipboardViewer)
  14.                         nextClipboardViewer = m.LParam;
  15.                     else
  16.                         SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
  17.                     break;
  18.                 default:
  19.                     base.WndProc(ref m);
  20.                     break;
  21.             }
  22.         }
复制代码
    2、然后提交给User32.dll处理:
  1.         [DllImport("User32.dll")]
  2.         protected static extern int SetClipboardViewer(int hWndNewViewer);
  3.         [DllImport("User32.dll", CharSet = CharSet.Auto)]
  4.         public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
  5.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  6.         public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
复制代码
    通过上面的代码,我们解决了第一个问题:如何监听Ctrl+C或者Ctrl+X等事件。
     二、在WCF中,我们要通过NetPeerTcpBinding实现P2P。
     下面我就一步一步的实现这个P2P的应用服务。
    1、定义契约和实现契约:
  1.    [ServiceContract(CallbackContract = typeof(IShare))]
  2.     public interface IShare
  3.     {
  4.        [OperationContract(IsOneWay = true)]
  5.        void ShareClipboard(string type,string message);
  6.     }
复制代码
  1.     public class ShareImplementation : IShare
  2.     {
  3.         private static Form m_receiverForm;
  4.         private  static ClipEventHandler m_OnClipReceive;
  5.         public void ShareClipboard(string type,string message)
  6.         {
  7.             try
  8.             {
  9.                 m_receiverForm.Invoke(m_OnClipReceive, type, message);
  10.             }
  11.             catch (Exception e)
  12.             {
  13.                 MessageBox.Show(e.ToString());
  14.             }
  15.         }
  16.        public void SetForm(Form form,ClipEventHandler theCallback)
  17.        {
  18.            m_receiverForm = form;
  19.       
  20.            m_OnClipReceive = theCallback;
  21.        }
  22.     }
  23.    使用一个类来管理这个服务:
复制代码
  1.     public class Peer
  2.     {
  3.         public string Id { get; private set; }
  4.         public IShare Channel;
  5.         public ShareImplementation Host;
  6.         public ClipEventHandler clipeventhandler;
  7.         public Form form;
  8.         public Peer(string id)
  9.         {
  10.             Id = id;
  11.         }
  12.         private DuplexChannelFactory<IShare> _factory;
  13.            public void StartService()
  14.     {
  15.         var binding = new NetPeerTcpBinding();
  16.         binding.Security.Mode = SecurityMode.None;
  17.         var endpoint = new ServiceEndpoint(
  18.             ContractDescription.GetContract(typeof(IShare)),
  19.             binding,
  20.             new EndpointAddress("net.p2p://SimpleP2P"));
  21.         Host = new ShareImplementation();
  22.         Host.SetForm(form,clipeventhandler);
  23.         _factory = new DuplexChannelFactory<IShare>(new InstanceContext(Host), endpoint);
  24.         var channel = _factory.CreateChannel();
  25.         ((ICommunicationObject)channel).Open();
  26.         // wait until after the channel is open to allow access.
  27.         Channel = channel;
  28.     }
  29.     public void StopService()
  30.     {
  31.         ((ICommunicationObject)Channel).Close();
  32.         if (_factory != null)
  33.             _factory.Close();
  34.     }
  35.     private readonly AutoResetEvent _stopFlag = new AutoResetEvent(false);
  36.     public void Run()
  37.     {
  38.         Console.WriteLine("[ Starting Service ]");
  39.         StartService();
  40.         Console.WriteLine("[ Service Started ]");
  41.         _stopFlag.WaitOne();
  42.         Console.WriteLine("[ Stopping Service ]");
  43.         StopService();
  44.         Console.WriteLine("[ Service Stopped ]");
  45.     }
  46.     public void Stop()
  47.     {
  48.         _stopFlag.Set();
  49.     }
  50.     }
复制代码
在WindowsForm中,通过DisplayClipboardData()方法来调用此服务,代码如下。
  1.         void DisplayClipboardData()
  2.         {
  3.             try
  4.             {
  5.                 IDataObject iData = new DataObject();
  6.                 string type = "",message="";
  7.               
  8.                 iData = Clipboard.GetDataObject();
  9.                 if (Clipboard.ContainsText())
  10.                 {
  11.                     message = (string)iData.GetData(DataFormats.Text);
  12.                 }
  13.          
  14.                 if (peer != null && peer.Channel != null)
  15.                 {
  16.                     peer.Channel.ShareClipboard("text", message);
  17.                 }
  18.             }
  19.             catch (Exception e)
  20.             {
  21.                 MessageBox.Show(e.ToString());
  22.             }
  23.         }
复制代码
还有就是一个方法来接受信息方法AddToClip,代码如下:
  1.         public void AddToClip(string type, string message)
  2.         {
  3.             if (type == "rtf")
  4.             {
  5.                 IDataObject iData = new DataObject(DataFormats.Rtf, message);
  6.                 richTextBox1.Rtf = (string)iData.GetData(DataFormats.Rtf);
  7.                 //richTextBox1.Rtf = message;
  8.             }
  9.             else if (type == "text")
  10.                 richTextBox1.Text = message;
  11.             else
  12.                 richTextBox1.Text = "[Clipboard data is not RTF or ASCII Text]";
  13.             richTextBox1.Text = message;
  14.         }
复制代码
由于WCF得回调和WindowsForm的主线程不是一个,故使用了一个委托:
  1.     public delegate void ClipEventHandler(string type ,string clipData);
复制代码
其他详细见代码。
实例的效果:
    在电脑zhuqilin上复制文本数据
3.png

   在电脑Colin上显示zhuqilin上复制的数据:
4.jpeg

总结:
      上星期用WCF的双工实现了一个音频聊天室的程序。有园友提出点对点的视频、语音、聊天用P2P去实现效率和性能更好,故研究了一下WCF的P2P。本文就是一个简单的WCF的P2P的例子。
扩展:
    这篇文章只实现了文字剪贴板的共享功能。如果你有兴趣,可以进一步扩展。
        扩展1:数据直接传递到其他电脑的剪贴板上,可以直接Ctrl+V粘贴。
        扩展2:现在只是实现文字剪贴板的共享。扩展成文件、视频、图片都可以。
    效果可以是:如果局域网的两个端点机器通过共享自己的剪贴板。在A机器上复制文件,在B机器上可以直接粘贴。
    写这个例子的灵感来自RealVNC。用过RealVNC的童鞋都知道,无论局域网还是外网,只要两台pc建立连接,就能共享剪贴板上的数据了。
最后:建立P2P和打开P2P管道需要时间,故在运行这个程序的之后,需要等上一段时间才能共享你的剪贴板。如果有建议请留言,有帮助请推荐。thx。
代码:https://files.cnblogs.com/zhuqil/ShareClipboard.rar


(全文完)
以下为广告部分
您部署的HTTPS网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!
5.png

SSL检测评估
快速了解HTTPS网站安全情况。
安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。
SSL证书工具
安装部署SSL证书变得更方便。
SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。
SSL漏洞检测
让服务器远离SSL证书漏洞侵扰
TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册