65.9K
CodeProject 正在变化。 阅读更多。
Home

P2P 通信 - 代理监听器和代理客户端

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (3投票s)

2008年4月20日

CPOL

4分钟阅读

viewsIcon

60165

downloadIcon

2195

通过 Web 代理进行通信的监听器和客户端对象的实现。

引言

沟通是我在工作项目和纯粹娱乐性项目中都有很多经验的问题。.NET Remoting 使沟通更加容易,但如果你用过它并遇到过“Remoting Exception”错误,你就会明白为什么我不喜欢它。希望 WCF 能纠正其中一些问题。无论如何,如果你想进行 P2P(点对点)通信,你就必须处理像 UPNP、VPN 或某种代理这样的东西。这是我的 Web 代理实现。

背景

P2P 通信是我在应用程序中遇到的几次问题。我做过几个 Messenger 类应用程序,它们通过 TcpClientsTcpListener 进行通信。使用它们的唯一问题是,你的通信仅限于你的本地局域网。最近,我做了一个与多个 Web 服务通信的 Messenger 应用程序,它会定期轮询它们以获取新的用户列表、消息等。这可以正常工作,但基于一群客户端轮询 Web 服务器的通信并不好。下面是我解决此问题方案的概述。这些线代表发送到 HttpHandler Server.ashxWebRequests,它正在等待另一个客户端将其数据发送到其终端。我模仿了 TcpClientTcpListener,并在它们之间插入了一个代理。问题解决了,在很大程度上。

Proxy

Using the Code

在尝试使用这些对象之前,我假设你具备套接字通信的基本知识,并且使用过 TcpClientsTcpListeners。我创建的代理版本非常相似,只是 ProxyClient 有一个 SendData 方法和一个 Receiving 事件,而不是一个你可以读写的 Stream

你需要做的第一件事就是让代理 Web 服务器运行起来。如果你打开代理解决方案,我指的是 ProxyService 网站。如果你对其进行任何修改,请确保下面的 web.config 行保持不变。这会注册 HttpHandler Server.ashx

    <system.web>
        <httpHandlers>
            <add verb="*" path="*.ashx" type="ProxyServer.Server, ProxyServer"/>
        </httpHandlers> 

接下来,你需要建立一些连接。创建一个 ProxyListener 来开始监听,创建一个 ProxyClient 来连接它。为了使事情更简单,你想从 ProxyClient 发送到 ProxyClient 的任何对象都需要继承 ProxyCommon 项目中的 DataMessage。这会给你的对象一个 SendEndPointRecieverEndPoint。如果你想做一个客户端/服务器应用程序,你的服务器端代码看起来会像这样。

App.Config

  <appSettings> 
    <add key="ProxyServer" value="https://:52318/ProxyService/Server.ashx"/>
    <add key="ProxyServerName" value="Test Server"/>
  </appSettings>

主机通信

string ServerName = ConfigurationManager.AppSettings["ProxyServerName"];
ProxyListener Listener = new ProxyListener(ServerName);
Listener.Start();
ProxyClient Client = Listener.AcceptProxyClient();
string Txt = "Some message I want to send";
StringMessage Msg = new StringMessage(Txt, Client.ClientEndPoint, Client.ServerEndPoint);
Client.SendData(Msg.ToByteArray());

现在是客户端。ProxyListener 基于 ServerName 开始监听。代理服务器将其用作键,并为其创建一个 EndPoint。当你创建一个 ProxyClient 来与监听器通信时,它连接到相同的 ServerName。代理服务器映射 EndPoints,然后两个 ProxyClients 都准备好通信。

ProxyClient Client = new ProxyClient();
Client.Recieving += new EventHandler<RecievingEventArgs>(Client_Recieving);
string ServerName = ConfigurationManager.AppSettings["ProxyServerName"];
Client.Connect(ServerName);
string Txt = "Some message I want to send";
StringMessage Msg = new StringMessage(Txt, Client.ClientEndPoint, Client.ServerEndPoint);
Client.SendData(Msg.ToByteArray());

void Client_Recieving(object sender, RecievingEventArgs e)
{
    StringMessage Msg = new StringMessage(e.Data);
    //The Client received a message, do something with it!
}

关注点

  1. ProxyClient 类与你可能熟悉的 TcpClient 类之间的一个主要区别是,你无法访问单个 Stream 来进行读写。这是因为底层的 stream 来自 HttpWebRequestWebResponse
  2. 这个想法有一些我还没有解决的缺陷。由于代理存在于 Web 服务器上,并且在应用程序缓存中存储了消息队列、终端等,如果 Web 服务器重启,你的连接就会丢失,需要重新建立。如果你使用的是 GoDaddy 等共享托管服务,这个问题可能会更严重,因为 GoDaddy 似乎每天都会重启一次。 ;-)
  3. 这种方法绝对适用于发送小的 P2P 信息。我考虑过通过它发送小文件或序列化对象,但仅此而已。你的通信速度会比直接使用套接字连接慢,因为数据流必须通过 Web 服务器。如果你想真正地 P2P 流式传输大量数据,这可能不够快。

历史

  • 2008 年 4 月 20 日:首次发布

这是我第一次尝试为 P2P 通信编写 ClientListener 包装器。这是一个进行中的项目,所以我乐于接受建议。一旦我对这种通信方式有了一定的完善,我计划编写另一个更适合网络游戏、视频流等通信的包装器。如果有人有关于如何使用 UPNP / 端口转发 / 隧道进行 P2P 通信的建议,请告诉我。

© . All rights reserved.