Click here to Skip to main content
Click here to Skip to main content

P2P Communication - Proxy Listeners and Proxy Clients

, 19 Apr 2008
Rate this:
Please Sign up or sign in to vote.
Implementation of Listener and Client objects that communicate through a Web proxy

Introduction

Communication is a problem I have had plenty of dealings with in work related projects and projects that are just for fun. .NET remoting makes communication easier but if you have ever used it and received one of their "Remoting Exception" errors, you can understand why I don't like it. Hopefully WCF corrects some of these problems. Either case, if you want to communicate P2P (Peer to Peer) then you either have to deal with something like UPNP, VPN, or proxy of some kind. This is my implementation of a Web proxy.

Background

P2P communication is a problem I've run into several times with my applications. I've made several Messenger type applications that communicate with TcpClients and a TcpListener. The only problem with using them is that your communication is limited to your local area network. Recently, I made another Messenger application that communicates with several Web services and it polls them periodically to get a new list of users, messages, etc. This works fine but having communication that is based on a bunch of clients polling a Web server is not so good. Below is an outline of my solution to this problem. The lines represent WebRequests that are made to an HttpHandler Server.ashx that are waiting for another client to send data to their end point. I modelled this after TcpClient and TcpListener and stuck a Proxy in between their communication. Problem solved, for the most part.

Proxy

Using the Code

Before you try these objects out, I am assuming you have basic knowledge of socket communication and you have used TcpClients and TcpListeners. Their Proxy counterparts I've made are very similar except that ProxyClient has a SendData method and a Receiving event instead of a Stream that you can read/write to.

The first thing you need to do is get the Proxy Web Server up and running. If you open the Proxy solution, I am talking about the ProxyService Web site. If you modify this at all, make sure the web.config lines below stay put. This registers the HttpHandler Server.ashx.

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

Next, you need to make some connections. Make a ProxyListener that will start Listening and a ProxyClient that connects to it. To make things easier, any object you want to send from ProxyClient to ProxyClient needs to inherit from DataMessage in the ProxyCommon project. This gives your object a SendEndPoint, and RecieverEndPoint. If you wanted to do a client / server app, your server side code would look something like this.

App.Config

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

Host Communication

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());

Now for the client side. A ProxyListener starts listening based on a ServerName. The proxy server uses this as key and makes an EndPoint for it. When you create a ProxyClient to communicate with the listener, it is connecting to the same ServerName. The proxy server maps the EndPoints and then both ProxyClients are ready to communicate.

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!
}

Points of Interest

  1. The major difference between the ProxyClient class and the TcpClient class which you may be used to is that you can't get to a single Stream to read / write to. This is because the underlying streams are coming from HttpWebRequest and WebResponse.
  2. This idea has a few flaws in it that I haven't worked out. Since the proxy exists on a Web server and has a message queue, endpoints, and such stored in the app cache, if the Web server ever restarts, your connections are lost and need to be reestablished. This can be a bigger problem if you are using a shared hosting service such as GoDaddy, which seems to restart on me once a day. Wink | ;-)
  3. This method will definitely work sending P2P information that is small. I would consider sending small files or serialized objects over it but that's about it. Your communication will be slower than connecting directly with sockets because the streams are having to go through the Web server. If you want to really stream lots of data P2P, this is probably not going to be fast enough.

History

  • 20th April, 2008: Initial post

This is my first attempt at writing Client and Listener wrappers for P2P communication. It's a work in progress, so I am open for suggestions. After I get this communication somewhat perfected, I'm planning on writing another communication wrapper that would be better suited for network gaming, video streaming, etc. If anyone has suggestions on how to do P2P communication with UPNP / port forwarding / tunnelling, please let me know.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Victor Pirkle
Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

 
JokeNice solution! Pinmemberngocdonghack200127-Mar-09 17:49 
GeneralRe: Nice solution! PinmemberBugslayer122-Oct-09 11:22 
GeneralDid your program connect through the right connection? Pinmemberngocdonghack200122-Oct-09 15:45 
GeneralRe: Did your program connect through the right connection? PinmemberBugslayer123-Oct-09 11:27 
GeneralReally cool Pinmemberevolved21-Apr-08 3:19 
GeneralRe: Really cool PinmemberVictor Pirkle21-Apr-08 4:52 
GeneralRe: Really cool PinmemberVictor Pirkle21-Apr-08 6:12 
Actually, you may not need to change anything for this to work with load balancing. Its been a while since I have thought about load balancing Smile | :) I think the web sites Application cache (Application["SomeKey"]) is the same memory even though you are load balancing. If thats the case, then nothing has to change and this will work as is for load balancing.
GeneralRe: Really cool Pinmemberevolved21-Apr-08 6:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 20 Apr 2008
Article Copyright 2008 by Victor Pirkle
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid