Generic P2P Architecture, Tutorial and Example - CodeProject

Generic P2P Architecture, Tutorial and Example

By dzzxyz | 15 Mar 2004

Generic P2P architecture, tutorial and example that covers basic P2P strategy. Upon completing this tutorial, you will be proficient in basic P2P design and coding.

Is your email address OK? You are signed up for our newsletters but your email address has not been reconfirmed in a long time. To make this warning go away please click here to have a confirmation email sent so we can confirm your email address and continue sending you your newsletters. Alternatively, you can update your subscriptions.

This generic P2P architecture tutorial was brought to you by Planet API � Searching thousands of ASPX / ASP.NET Public Webmethods / Public Webservices, Search Engine APIs, Novelty APIs, B2B APIs, Game APIs, P2P APIs, Fun APIs, AI Chatbot APIs, etc.

Overview of P2P Culture

P2P (Peer To Peer) is when multiple computers think collectively towards a shared objective. Computer programs that use less central servers and rely on a collection of computers such as Gnutella, distributed media streaming, networks of DCC based IRC fservers etc. tend to be referred to as being more P2P. Computer programs where many end-users communicate with few central services tend to be referred to as being less P2P or not P2P. To fully understand and leverage P2P technology, one must separate his or her self from the dogma that our computer programs must be united by servers in our physical possession to synchronize activities. Rather, think of our computer programs from a more digital-life oriented perspective and break the computer software up over multiple machines and make no single part of the software critical to the collective objective.

P2P Philosophy

�Single servants are less powerful then a single server but the collective of many servants is more powerful then any single server� - Daniel Stephen Rule.

For example, a large software company gives each employee a very small amount of responsibility. Even if this means you get your month�s coding done in a few days, it is more beneficial to the company as a whole to not rely on any single employee too much and allows the company more overall stability and to ultimately write larger more complex software packages than any single person is capable of. Your software is more P2P if you leverage this same principle to achieve more bandwidth and computing speed.

Basic P2P Terminology
Peer or Servant

A computer program that acts as both a client and a server for the entire P2P network.

Connection Manager

A light server application that provides a starting point for applications which enter a P2P network. The less the connection manager is involved in the objective of your overall application, the more P2P your application is. The more P2P your application is, the less strain on your own hardware.

Simple P2P Chat Example

This example demonstrates a very simple but highly P2P application. This example consists of two fundamental P2P parts: a connection manager and a servant. The connection manager should be compiled and executed once. The servant should be compiled and its config.xml�s connectionmgr tag should be set to the IP address or domain name of the computer that is running the connection manager. Make multiple copies of the servant�s executable and config.xml and place them on multiple computers. Execute each servant on a different machine and they will contact the connection manager to resolve each other�s location and network with each other. Each servant will frequently ask the connection manager who is on the P2P network and keep their own publish list up to date. When a servant leaves the network, an updated list is published to all the other servants and they discontinue attempting to communicate with the servant who left.

Can I still try this out if I only have one computer to work with?

Yes. The connection manager assigns a new port number to each servant so each servant listens on a unique port number. You can run the servant executable as many times as you want on a single machine. For your first test, I would suggest running the connection manager once and then run the servant a couple of times on the same machine as the connection manager. Then chat in the servant windows to verify that the P2P network has been constructed on your computer. If you have other computers to work with, simply execute the servant on the other computers and chat to verify that they successfully joined the P2P network.

The configuration file:
Put the IP address of the server that has the connection manager here.
   127.0.0.1 

Leave this 85 unless you change the port that the connection manager sits on:

   85

List the IP addresses or domain names that you wish this servant to ignore: 
1.1.1.1 

     fooUser234.fooISP23423.com 
   

What are the ban tags for?

The ban tags allow each servant to list the IP addresses or domain names that they do not wish to get data from.

The Connection Manager

Add a peer to the connection manager�s knowledge of the P2P network.

Collapse | Copy Code

Private Sub p2p_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    iPortMax = iPortMax + 1
    Dim a As Integer
    For a = 1 To p2p.UBound
        Dim istate As Integer
        istate = p2p(a).State
        If istate = 0 Or istate = 8 Then
            Call EnterCriticalSection(tCritSection)
            RemovePeerByOffset CStr(a)
            p2p(a).Close
            p2p(a).Accept requestID
            AddPeer p2p(a).RemoteHostIP, CStr(iPortMax), CStr(a)
            Call LeaveCriticalSection(tCritSection)
            Exit Sub
        End If
        DoEvents
    Next a
    DoEvents
    Dim i As Integer
    i = p2p.UBound
    Call EnterCriticalSection(tCritSection)
    Load p2p(i + 1)
    p2p(i + 1).Accept requestID
    AddPeer p2p(i + 1).RemoteHostIP, CStr(iPortMax), CStr(i + 1)
    Call LeaveCriticalSection(tCritSection)
End Sub 

A servant wants a list of all its peers.

Collapse | Copy Code

Private Sub p2p_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    Dim a As String
    If p2p(Index).State <> 7 Then p2p(Index).Close: Exit Sub
    p2p(Index).GetData a
    If a = "needs peer list" Then
        On Error GoTo exit_critical_list
        Call EnterCriticalSection(tCritSection)
        Dim pPersonalPeerDoc As MSXML2.DOMDocument
        Set pPersonalPeerDoc = New MSXML2.DOMDocument
        pPersonalPeerDoc.loadXML pDoc.xml
        pPersonalPeerDoc.selectSingleNode("./peers/peer[offset = '" &_
                                           Index & "']/me").Text = "TRUE"
        p2p(Index).SendData pPersonalPeerDoc.xml
exit_critical_list:
        On Error Resume Next
        Call LeaveCriticalSection(tCritSection)
    Else
        MsgBox Index & " sent: " & a & " to the connection manager"
    End If
End Sub 

A servant left the network.

Collapse | Copy Code

Private Sub p2p_Close(Index As Integer)
        Call EnterCriticalSection(tCritSection)
            RemovePeerByOffset CStr(Index)
        Call LeaveCriticalSection(tCritSection)
End Sub
The Servants

The connection manager has a new list of this servant�s peers.

Collapse | Copy Code

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim document As String
    If Winsock1.State <> 7 Then Winsock1.Close: Exit Sub
    Winsock1.GetData document
    pDoc1.loadXML document

    Dim pPeerList As MSXML2.IXMLDOMNodeList
    Set pPeerList = pDoc1.selectNodes("./peers/peer/port")
    userList1.Clear
    Dim i As Integer
    For i = 0 To pPeerList.length - 1
        If pPeerList(i).Text = _
          pDoc1.selectSingleNode("./peers/peer[me = 'TRUE']/port").Text Then
            userList1.AddItem "*" & pPeerList(i).Text
        Else
            userList1.AddItem pPeerList(i).Text
        End If
    Next
    servants1(0).Close
    servants1(0).LocalPort = _
      CInt(pDoc1.selectSingleNode("./peers/peer[me = 'TRUE']/port").Text)
    servants1(0).Listen
End Sub

This servant is connecting to all of its peers and publishing some data to all of them.

Collapse | Copy Code

Private Sub txtSend1_KeyPress(KeyAscii As Integer)
On Error Resume Next
 If KeyAscii = 13 Then
  iSendsLeft1 = pDoc1.selectNodes("./peers/peer").length
  Dim i As Integer
  For i = 0 To pDoc1.selectNodes("./peers/peer").length - 1
   Dim iIp As String
   Dim iPort As Integer
   iIp = _
    pDoc1.selectNodes("./peers/peer").Item(i).selectSingleNode("./ip").Text
   iPort = _
    CInt(pDoc1.selectNodes("./peers/peer").Item(i).selectSingleNode("./port").Text)
   Dim strState As String
   While send1.State = 6
       DoEvents
   Wend
   send1.Close
   send1.Connect iIp, iPort
  Next
 End If
 DoEvents
End Sub

A peer of this servant wants to connect.

Collapse | Copy Code

Private Sub servants1_ConnectionRequest(Index As Integer,_
                                          ByVal requestID As Long)
    Dim remoteip As String
    Dim remoteaddy As String
    remoteip = servants1(Index).RemoteHostIP
    remoteaddy = servants1(Index).RemoteHost
    If (pConfig.selectNodes("./config/bans/ban[target = '"_
      & remoteip & "']").length = 0) _
      And (pConfig.selectNodes("./config/bans/ban[target = '" _
      & remoteaddy & "']").length = 0) Then
        Dim a As Integer
        For a = 1 To servants1.UBound
            If servants1(a).State = 0 Or servants1(a).State = 8 Then
                Call EnterCriticalSection(tCritSection)
                servants1(a).Close
                servants1(a).Accept requestID
                Call LeaveCriticalSection(tCritSection)
                Exit Sub
            End If
            DoEvents
        Next a
        DoEvents
        Call EnterCriticalSection(tCritSection)
        Dim i As Integer
        i = servants1.UBound
        Load servants1(i + 1)
        servants1(i + 1).Accept requestID
        Call LeaveCriticalSection(tCritSection)
    End If
End Sub

A peer of this servant has some data for it.

Collapse | Copy Code

Private Sub servants1_DataArrival(Index As Integer,_
                                   ByVal bytesTotal As Long)
On Error Resume Next
    Dim a As String
    If servants1(Index).State <> 7 Then servants1(Index).Close: Exit Sub
    servants1(Index).GetData a
    txtChat1.Text = txtChat1.Text & vbCrLf & a
End Sub
Why don�t my P2P servants communicate with other servants on the Internet when they are behind a router?

Some routers have default communication restrictions called a �Firewall�. These restrictions are intended to prevent a virus from misusing your computer and to force you to explicitly disable them if and when you need more access to the Internet. One of the most common restrictions that harm P2P networks is when the router blocks most outgoing ports by default. You can test to see if your router is blocking a port by:

  1. Run a copy of the connection manager on a computer behind your router.
  2. On a computer outside the router on the Internet, open a DOS box and type in �telnet 85�.
  3. Your connection manager on the computer behind the firewall should display:

    Collapse | Copy Code

            ip of peer
            2224
            1
            FALSE
    

If not then you need to enable port 85 in your router for the connection manager. This also has to be done for each peer behind a router with a built in firewall.

You can still leverage P2P technology on your personal network (behind your router) as long as all of your peers and your connection manager are behind your firewall. Each peer must be configured with the IP address of the connection manager that the router has assigned to it. I would highly suggest having the router assign the connection manager machine a static IP. This way, peers do not have to be reconfigured each time you reboot the box with the connection manager on it. The servants, however, can just get a dynamic IP address from your router every time they boot up because they will use the connection manager to resolve each other's location.

But I really need both servants behind routers and servants on the Internet to all be part of my P2P network.

This topic is outside the scope of this article, but in short here is one common solution used by other P2P technologies:

  1. Set your connection manager on a box that is intended to be a web server. If your connection manager is behind a router then configure your router to block all incoming ports but make the router forward port 85 connections to the machine that is running the connection manager.
  2. Have each servant report to the connection manager any peers that they are unable to contact. Have the connection manager determine if they are behind a port blocking router by seeing if the suspicious servant sends another heart beat. If most peers are complaining that they can�t connect to a suspicious servant but the suspicious servant continuously asks the connection manager for a user list then the connection manager can conclude that the servant is probably behind a port blocking router.
  3. If the connection manager makes this determination, have it notify the suspicious servant that it needs to pull from another peer. For the life of the suspicious servant instance, it pulls from another peer who publishes any data that it gets. The chosen peer must not itself be a suspicious peer behind a router.

This will slow the P2P network down but will allow peers behind port blocking routers to join the P2P network. I would not suggest having the connection manager just assume that a peer is suspicious instantly when the other peers complain about it, rather it should have a threshold of 2 or 3 complaints from each of the other peers before telling it that it is suspicious and assigning it a chosen peer to pull from.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

时间: 2024-11-02 00:08:26

Generic P2P Architecture, Tutorial and Example - CodeProject的相关文章

red hat enterprise 5.4下安装mysql 5.6.10

完成上一次留下的话题,今天谈谈在red hat enterprise 5.4 下安装mysql 5.6.10 1:下载mysql 下载地址为:http://www.mysql.com/downloads/mysql/5.6.html#downloads 选择"Source Code"->"Generic Linux (Architecture Independent), Compressed TAR Archive" 当然还需要一个工具cmake(因为这个my

第二章排错的工具:调试器Windbg(上)

感谢博主 http://book.51cto.com/art/200711/59731.htm <Windows用户态程序高效排错>第二章主要介绍用户态调试相关的知识和工具.本文主要讲了排错的工具调试器Windbg.     第二章 汇编.异常.内存.同步和调试器--重要的知识点和神兵利器 这一部分主要介绍用户态调试相关的知识和工具.包括汇编.异常exception.内存布局.堆heap.栈stack.CRTC Runtime.handle/Criticalsection/thread con

C++编写安全OCX,IE不弹出安全提示

下面将分别介绍在MFC ActiveX和ATL中如何标记一个控件为安全的控件.        要标记一个MFC ActiveX控件为安全,可以仿照下面代码修改而得:   // CardScan.cpp : CCardScanApp 和DLL 注册的实现.#include "stdafx.h"#include "CardScan.h"#include "comcat.h"#include "strsafe.h"#include 

Linux/Redhat源码编译安装mysql5.5教程

一.源码编译安装mysql5.5.2 操作系统:Redhat Enterprise Linux 6.2 1. 创建用户.目录和修改权限 # mkdir -p /usr/local/mysql/data # groupadd mysql # useradd -g mysql mysql # chown -R mysql.mysql /usr/local/mysql/data/ 2. 安装所需相关库文件 # yum install -y gcc gcc-c++ gcc-g77 autoconf au

《计算机网络:自顶向下方法(原书第6版)》一2.1 应用层协议原理

2.1 应用层协议原理 假定你对新型网络应用有了一些想法.也许这种应用将为人类提供一种伟大的服务,或者将使你的教授高兴,或者将带给你大量的财富,或者只是在开发中获得乐趣.无论你的动机是什么,我们现在考察一下如何将你的想法转变为一种真实世界的网络应用. 研发网络应用程序的核心是写出能够运行在不同的端系统和通过网络彼此通信的程序.例如,在Web应用程序中,有两个互相通信的不同的程序:一个是运行在用户主机(桌面机.膝上机.平板电脑.智能电话等)上的浏览器程序:另一个是运行在Web服务器主机上的Web服

Linux下基于源码方式安装MySQL 5.6

    MySQL为开源数据库,因此可以基于源码实现安装.基于源码安装有更多的灵活性.也就是说我们可以针对自己的硬件平台选用合适的编译器来优化编译后的二进制代码,根据不同的软件平台环境调整相关的编译参数,选择自身需要选择不同的安装组件,设定需要的字符集等等一些可以根据特定应用场景所作的各种调整.本文描述了如何在源码方式下安装MySQL.   1.安装环境及介质#安装环境SZDB:~ # cat /etc/issueWelcome to SUSE Linux Enterprise Server 1

Linux系统下Mysql数据库安装配置整理

Mysql安装 1.通过官网下载mysql源码包.http://dev.mysql.com/downloads/ 点击MySQL Community Server,选择Source Code, 点击 Generic Linux (Architecture Independent), Compressed TAR Archive后的Download # wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.20.tar.gz # t

SUSE Linux下源码编译方式安装MySQL 5.6过程分享_Mysql

MySQL为开源数据库,因此可以基于源码实现安装.基于源码安装有更多的灵活性.也就是说我们可以针对自己的硬件平台选用合适的编译器来优化编译后的二进制代码,根据不同的软件平台环境调整相关的编译参数,选择自身需要选择不同的安装组件,设定需要的字符集等等一些可以根据特定应用场景所作的各种调整.本文描述了如何在源码方式下安装MySQL. 1.安装环境及介质 复制代码 代码如下: #安装环境 SZDB:~ # cat /etc/issue Welcome to SUSE Linux Enterprise

CentOS系统安装mysql5数据库两种方法

简单点说,就是yum安装软件容易点,会自动解决各个包的依赖关系.rpm就一个软件包. CentOS下以RPM方式安装MySQL5.5 首先去http://dev.mysql.com/downloads/mysql/5.5.html#downloads站点下载: 分别下载以下三个文件(由于我的机器是32位,下面是32位版本的包,如果你的机器是64位的请下载64位版本): MySQL-server-5.5.16-1.rhel5.i386.rpm MySQL-client-5.5.16-1.rhel4