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

Peer Name Resolution (PNRP) - 对等方名称解析 (PNRP)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (22投票s)

2005年10月27日

8分钟阅读

viewsIcon

95959

downloadIcon

1224

Introduction to Peer Name Resolution and Microsoft's Peer-to-Peer technology. - 对等方名称解析和 Microsoft 对等网络技术的简介。

Sample Image

背景

This is the first article of many, where I will talk about the practical uses of Microsoft's Peer-to-Peer technology. Peer-to-Peer technology has been around since the late 90's. There have been several articles written for CodeProject that discuss the various aspects and implementations of a peer-to-peer infrastructure. There are also several open-source implementations including Gnucleus and Shareaza. - 这是许多文章中的第一篇,我将讨论 Microsoft 对等网络技术的实际应用。对等网络技术自 90 年代末以来就已存在。CodeProject 上已经有几篇文章讨论了对等网络基础设施的各个方面和实现。还有一些开源实现,包括 GnucleusShareaza

Microsoft recognized the value of this technology and spun up various research projects to investigate and document implementation approaches. Pastry was the earliest project that I recall that tackled the issues involved in building a peer-to-peer network. By late 2003, Microsoft released the Advanced Networking Pack for Windows XP SP1 which added basic Peer-to-Peer technology plumbing into Windows. While characteristically late to the game, their implementation recognized the value of using IPv6 as the foundation for building peer-to-peer networks. Microsoft has subsequently rolled this technology into Windows XP Service Pack 2 and continues to expand the infrastructure's capabilities into Windows Vista. Finally, given the nature of the technology, it's interesting to note that Microsoft has not included this support on any of its server platforms. - Microsoft 认识到这项技术的价值,并启动了各种研究项目来调查和记录实现方法。我记得最早的项目是 Pastry,它解决了构建对等网络所涉及的问题。到 2003 年底,Microsoft 发布了 Windows XP SP1 的高级网络包,为 Windows 添加了基本的对等网络技术基础。虽然通常是后来者,但他们的实现认识到使用 IPv6 作为构建对等网络基础的价值。Microsoft 随后将这项技术推广到 Windows XP Service Pack 2,并继续将其基础设施功能扩展到 Windows Vista。最后,鉴于这项技术的性质,值得注意的是 Microsoft 未在其任何服务器平台上包含此支持。

引言

Microsoft's entire Peer-to-Peer technology is exposed through the latest Platform SDK as C/C++ API calls. That's great for anyone who still develops applications in unmanaged code or managed C++. However, I'm a big fan of .NET managed code, and have been busy importing each API call into C# and creating a managed framework to simplify, as much as possible, peer-to-peer application development in .NET. So, without further delay, let's roll our sleeves up and dig in. - Microsoft 的整个对等网络技术通过最新的 Platform SDK 以 C/C++ API 调用形式公开。这对于仍开发非托管代码或托管 C++ 应用程序的任何人来说都非常棒。然而,我是一个忠实的 .NET 托管代码爱好者,并且一直在忙于将每个 API 调用导入 C#,并创建一个托管框架,尽可能简化 .NET 中的对等应用程序开发。那么,事不宜迟,让我们撸起袖子开始吧。

Clouds - 云

As previously mentioned, IPv6 is at the heart of Microsoft's Peer-to-Peer technology. The beauty of IPv6 is that besides an address and port, a registered resource also has a scope. Scope was added to further identify the services/resources listening on a port. A group of resources connected in a peer-to-peer network using the same scope is also known as a Cloud. Clouds are closely related to IPv6 scopes but there are some minor differences. - 如前所述,IPv6 是 Microsoft 对等网络技术的核心。IPv6 的美妙之处在于,除了地址和端口之外,已注册的资源还有一个范围。添加范围是为了进一步标识正在监听端口的服务/资源。在对等网络中使用相同范围连接的资源组也称为云。云与 IPv6 范围密切相关,但存在一些细微差别。

A Cloud is like a membership at the YMCA, where only members (registered peers) can use the facilities (in this case, communicate). All members can use the facilities at any YMCA and so belong to the organization. In Peer-to-Peer terms, this organization is called the Global Cloud. The equivalent to individual YMCA facilities are called Link Clouds. That is, each LAN the computer is connected to has a Link Cloud. - 云就像在 YMCA 的会员资格,只有会员(已注册的对等方)才能使用设施(在这种情况下是通信)。所有会员都可以使用任何 YMCA 的设施,从而属于该组织。用对等网络术语来说,这个组织称为 Global Cloud(全局云)。相当于 YMCA 个人设施的是 Link Clouds(链接云)。也就是说,计算机连接到的每个 LAN 都有一个 Link Cloud。

The Global Cloud has the greatest range and allows applications to communicate over the Internet. Link clouds allow applications behind a firewall or connected through a common subnet to communicate. - Global Cloud 的范围最广,允许应用程序通过 Internet 进行通信。Link Clouds 允许防火墙后面的应用程序或通过公共子网连接的应用程序进行通信。

To enumerate the available clouds, you must indicate the scope of the search - 要枚举可用的云,您必须指示搜索范围

任意   Return any cloud the computer is connected to - 返回计算机连接到的任何云
全局   Return the global cloud - 返回全局云
LinkLocal - LinkLocal   Return any link local clouds - 返回任何链接本地云

Next comes a series of of Windows Socket calls to synchronously begin a lookup and iterate over the results - 接下来是一系列 Windows Socket 调用,用于同步开始查找并迭代结果

  • Call WSALookupServiceBegin to begin the enumeration and return a handle. - 调用 WSALookupServiceBegin 开始枚举并返回句柄。
  • Call WSALookupServiceNext to retrieve a set of clouds matching the scope. Call this function until the application has retrieved all the clouds. - 调用 WSALookupServiceNext 以检索与范围匹配的一组云。调用此函数直到应用程序检索到所有云。
  • Call WSALookupServiceEnd to finish the enumeration. - 调用 WSALookupServiceEnd 完成枚举。

To encapsulate this functionality, I created a Collection class that implements IEnumerable with an embedded class that implements IEnumerator. This allows a simple foreach loop to enumerate the clouds. - 为了封装此功能,我创建了一个 Collection 类,它实现了 IEnumerable,并带有一个实现了 IEnumerator 的嵌入式类。这允许一个简单的 foreach 循环来枚举云。

public class PeerCloudCollection : IEnumerable
{
    private static WSAService service = WSAService.Instance;
    private IEnumerator clouds;

    public PeerCloudCollection(PNRP_SCOPE Scope)
    {
       clouds = new PeerCloudEnumerator(Scope);
    }

    public PeerCloudCollection()
    {
      clouds = new PeerCloudEnumerator(PNRP_SCOPE.Any);
    }

    private class PeerCloudEnumerator : IEnumerator
    {
      private static Guid SVCID_PNRPCLOUD = new Guid(0xc2239ce6, 
              0xc0, 0x4fbf, 0xba, 0xd6, 0x18, 0x13, 0x93, 0x85, 0xa4, 0x9a);
      private IntPtr hLookup;
      private IntPtr pResults;
      private PNRP_SCOPE scope;

      public PeerCloudEnumerator(PNRP_SCOPE Scope)
      {
         scope = Scope;
         Reset();
      }

     ~PeerCloudEnumerator()
     {
        if (pResults != IntPtr.Zero) Marshal.FreeHGlobal(pResults);
        if (hLookup != IntPtr.Zero) PnrpNative.WSALookupServiceEnd(hLookup);
     }

#region IEnumerator Members

    public void Reset()
    {
        int err;
        if (hLookup != IntPtr.Zero)
        {
            err = PnrpNative.WSALookupServiceEnd(hLookup);
            if (err != 0)
             throw new 
               System.Net.Sockets.SocketException(PnrpNative.WSAGetLastError());
            hLookup = IntPtr.Zero;
            pResults = IntPtr.Zero;
        }
        
        CSADDR_INFO csaAddr = new CSADDR_INFO();
        PNRPCLOUDINFO pnrpCloudInfo = new PNRPCLOUDINFO();
        BLOB blPnrpData = new BLOB();
        WSAQUERYSET querySet = new WSAQUERYSET();
        
        pnrpCloudInfo.dwSize = Marshal.SizeOf(typeof(PNRPCLOUDINFO));
        pnrpCloudInfo.Cloud.Scope = scope;
        
        blPnrpData.cbSize = Marshal.SizeOf(typeof(PNRPCLOUDINFO));
        blPnrpData.pBlobData = Marshal.AllocHGlobal(blPnrpData.cbSize);
        Marshal.StructureToPtr(pnrpCloudInfo, blPnrpData.pBlobData, false);
        
        querySet.dwSize = Marshal.SizeOf(typeof(WSAQUERYSET));
        querySet.dwNameSpace = 39; // NS_PNRPCLOUD
        querySet.lpServiceClassId = 
           Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
        Marshal.StructureToPtr(SVCID_PNRPCLOUD, 
                querySet.lpServiceClassId, false);
        
        querySet.lpBlob = 
          Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BLOB)));
        Marshal.StructureToPtr(blPnrpData, querySet.lpBlob, false);
        
        IntPtr qryptr = 
          Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WSAQUERYSET)));
        Marshal.StructureToPtr(querySet, qryptr, false);
    
        err = PnrpNative.WSALookupServiceBegin(qryptr, 
              WSALookup.LUP_RETURN_ALL, out hLookup);
        if (err != 0)
         throw new 
           System.Net.Sockets.SocketException(PnrpNative.WSAGetLastError());
    }
    
    public object Current
    {
        get
        {
            WSAQUERYSET querySet = (WSAQUERYSET)
              Marshal.PtrToStructure(pResults, typeof(WSAQUERYSET));
            BLOB blPnrpData = (BLOB)
              Marshal.PtrToStructure(querySet.lpBlob, typeof(BLOB));
            PNRPCLOUDINFO pnrpCloudInfo = (PNRPCLOUDINFO)
              Marshal.PtrToStructure(blPnrpData.pBlobData, 
              typeof(PNRPCLOUDINFO));
            
            PeerCloud cloud = new PeerCloud(querySet.lpszServiceInstanceName, 
                      pnrpCloudInfo.Cloud.Scope, pnrpCloudInfo.Cloud.ScopeId);
            Marshal.FreeHGlobal(pResults);
            return cloud;
        }
    }

    public bool MoveNext()
    {
        int err = Pnrp.LookupServiceNext(hLookup, out pResults);
        if (err != 0) return false;
        return true;
    }

#endregion

    public IEnumerator GetEnumerator()
    {
        return clouds;
    }
    
    IEnumerator IEnumerable.GetEnumerator() 
    {
        return GetEnumerator();
    }
}

The Reset function passes a complicated set of data structures into the WSALookupServiceBegin function. The LUP_RETURN_ALL parameter tells the subsequent call to WSALookupServiceNext to fully populate the PNRPCLOUDINFO data structure. MoveNext uses the WSALookupServiceNext to retrieve the results. true or false is returned depending on whether a result was returned. The Current function marshals the data structures into managed equivalents and creates a PeerCloud class to represent each cloud as a managed object. The following VB code shows how to use this cloud collection - Reset 函数将一组复杂的数据结构传递给 WSALookupServiceBegin 函数。LUP_RETURN_ALL 参数告诉后续对 WSALookupServiceNext 的调用完全填充 PNRPCLOUDINFO 数据结构。MoveNext 使用 WSALookupServiceNext 来检索结果。是否返回结果决定了返回 truefalseCurrent 函数将数据结构封送到托管等价物,并创建一个 PeerCloud 类来将每个云表示为托管对象。以下 VB 代码显示了如何使用此云集合

For Each cloud As PeerCloud In New PeerCloudCollection(scope)
   Debug.Writeline(cloud.Name)
Next

Of course, before peers in a cloud can communicate, they must be able to locate each other. This is were Peer Name Resolution comes in. - 当然,在云中的对等方能够通信之前,它们必须能够相互定位。这就是 Peer Name Resolution 发挥作用的地方。

Peer Name Resolution (PNRP) - 对等方名称解析 (PNRP)

PNRP; it's a mouthful. It's also a serverless DNS technology that allows nodes to discover each other. Think about that for a second. It allows your Windows XP box to become its own DNS server. No need to pay $10 to register each domain name. But there's a catch; it's limited to the domain name pnrp.net. - PNRP;这有点拗口。它也是一种无服务器 DNS 技术,允许节点相互发现。想想看。它允许您的 Windows XP 计算机成为自己的 DNS 服务器。无需支付 10 美元注册每个域名。但有一个问题;它仅限于 pnrp.net 域名。

As the first letter in PNRP suggests, you must register a Peer Name. Peer names are fixed names for resources such as computers, users, groups, or services. This is similar to today's DNS except, instead of just IP addresses, the resources can be more granular. A Peer Name is a case-sensitive text string that has the format "Authority.Classifier". The value of Authority depends on whether the name is secured or unsecured. The value is always 0 for an unsecured Authority (secured names will be discussed in a later article). The value of Classifier is a text string name you give for the resource and cannot contain spaces. The following list shows some examples of peer names - 正如 PNRP 的第一个字母所示,您必须注册一个 Peer Name(对等方名称)。对等方名称是资源(如计算机、用户、组或服务)的固定名称。这与今天的 DNS 类似,只不过,资源可以更细粒度,而不是仅仅是 IP 地址。Peer Name 是一个区分大小写的文本字符串,格式为“Authority.Classifier”。Authority 的值取决于名称是受保护的还是不受保护的。对于不受保护的 Authority,该值始终为 0(受保护的名称将在后续文章中讨论)。Classifier 的值是您为资源指定的文本字符串名称,不能包含空格。以下列表显示了一些对等方名称的示例

  • 0.test - 0.test
  • 0.my.peername - 0.my.peername
  • 6520c005f63fc1864b7d8f3cabebd4916ae7f33d.test - 6520c005f63fc1864b7d8f3cabebd4916ae7f33d.test

PNRP uses peer names to identify resources in a peer network. The key here is "Peer Network". This isn't the whole IPv6 network that the computer is connected to, it's limited to just the resources available within a Cloud. Registering any resource not managed by the Peer-to-Peer networking APIs either will result in an error or won't be resolved later. - PNRP 使用对等方名称来标识对等网络中的资源。这里的关键是“Peer Network”(对等网络)。这不是计算机连接到的整个 IPv6 网络,它仅限于云中可用的资源。注册任何不由对等网络 API 管理的资源都会导致错误,或者以后无法解析。

Register and Unregister a Peer Name - 注册和注销对等方名称

To register an unsecured Peer Name, you must provide a valid unsecured Peer Name and an IP address. Optionally, you can indicate the Cloud name (Global by default) and an additional comment or description associated with the resource. This information is stored in the WSAQUERYSET data structure and passed to the WSASetService with the Register option. - 要注册一个不受保护的 Peer Name,您必须提供一个有效的不受保护的 Peer Name 和一个 IP 地址。可选地,您可以指定 Cloud 名称(默认为 Global)以及与资源关联的附加注释或描述。此信息存储在 WSAQUERYSET 数据结构中,并与 Register 选项一起传递给 WSASetService

public static void Register(PeerRegistration Registration)
{
    CSADDR_INFO csaAddr = new CSADDR_INFO();
    PNRPINFO pnrpInfo = new PNRPINFO();
    BLOB blPnrpData = new BLOB();
    WSAQUERYSET querySet = new WSAQUERYSET();
    
    //
    // fill a CSADDR_INFO structure from the address
    //
    csaAddr.iProtocol = 6; // IPPROTO_TCP
    csaAddr.iSocketType = 1; // SOCK_STREAM;
    csaAddr.LocalAddr.iSockaddrLength = 
            Marshal.SizeOf(typeof(SOCKADDR_IN6));
    csaAddr.LocalAddr.lpSockaddr = 
            Marshal.AllocHGlobal(csaAddr.LocalAddr.iSockaddrLength);
    Marshal.StructureToPtr(Registration.address, 
            csaAddr.LocalAddr.lpSockaddr, false);

    //
    // build the WSAQUERYSET required to register
    //
    pnrpInfo.dwSize = Marshal.SizeOf(typeof(PNRPINFO));
    pnrpInfo.dwLifetime = 60*60*8; // 8 hours
    if (Registration.Identity != string.Empty)
        pnrpInfo.lpwszIdentity = 
          Marshal.StringToHGlobalUni(Registration.Identity);
    
    blPnrpData.cbSize = Marshal.SizeOf(typeof(PNRPINFO));
    blPnrpData.pBlobData = Marshal.AllocHGlobal(blPnrpData.cbSize);
    Marshal.StructureToPtr(pnrpInfo, blPnrpData.pBlobData, false);
    
    querySet.dwSize = Marshal.SizeOf(typeof(WSAQUERYSET));
    querySet.dwNameSpace = 38; // NS_PNRPNAME
    querySet.dwNumberOfCsAddrs = 1; // one address
    querySet.lpServiceClassId = 
      Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
    Marshal.StructureToPtr(SVCID_PNRPNAMEV1, 
            querySet.lpServiceClassId, false);
    querySet.lpszServiceInstanceName = Registration.PeerName;
    if (Registration.CloudName != string.Empty)
        querySet.lpszContext = 
            Marshal.StringToHGlobalUni(Registration.CloudName);
    if (Registration.Comment != string.Empty)
        querySet.lpszComment = 
            Marshal.StringToHGlobalUni(Registration.Comment);

    querySet.lpcsaBuffer = 
       Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CSADDR_INFO)));
    Marshal.StructureToPtr(csaAddr, querySet.lpcsaBuffer, false);
    
    querySet.lpBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BLOB)));
    Marshal.StructureToPtr(blPnrpData, querySet.lpBlob, false);
    
    IntPtr qryptr = 
      Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WSAQUERYSET)));
    Marshal.StructureToPtr(querySet, qryptr, false);
    
    int err = PnrpNative.WSASetService(qryptr, 
                WSAESETSERVICEOP.Register, 0);
    if (err != 0)
     throw new 
      System.Net.Sockets.SocketException(PnrpNative.WSAGetLastError());
}

To unregister an unsecured Peer Name, you must provide a valid unsecured Peer Name and optionally the Cloud name (Global by default). This information is stored in the WSAQUERYSET data structure and passed to the WSASetService with the Delete option. While not listed here, the code is included in the download. - 要注销一个不受保护的 Peer Name,您必须提供一个有效的不受保护的 Peer Name,并可选地提供 Cloud 名称(默认为 Global)。此信息存储在 WSAQUERYSET 数据结构中,并与 Delete 选项一起传递给 WSASetService。虽然此处未列出,但代码包含在下载文件中。

Searching for a Peer Name - 搜索对等方名称

PNRP includes the ability to search for registered Peer Names. To resolve a Peer Name, you must provide the Peer Name, search criteria and optional cloud name (Global by default) and IP address hint. Typically, a lookup is used to determine if a Peer Name already exists or to contact it directly. The following search criteria options are supported - PNRP 包括搜索已注册对等方名称的功能。要解析 Peer Name,您必须提供 Peer Name、搜索条件以及可选的 Cloud 名称(默认为 Global)和 IP 地址提示。通常,查找用于确定 Peer Name 是否已存在或直接联系它。支持以下搜索条件选项

默认值   Uses the NonCurrentProcessPeerName option. - 使用 NonCurrentProcessPeerName 选项。
AnyPeerName - AnyPeerName   The matching peer name can be registered locally or remotely. - 匹配的对等方名称可以在本地或远程注册。
NearestNonCurrentProcessName - NearestNonCurrentProcessName   The matching peer name can be registered locally or remotely, but the resolve request excludes any peer name registered by the process making the resolve request and looks for the service closest to the local IP address. - 匹配的对等方名称可以在本地或远程注册,但解析请求会排除进行解析请求的进程注册的任何对等方名称,并查找最接近本地 IP 地址的服务。
NearestPeerName - NearestPeerName   The matching peer name can be registered locally or remotely, but the resolve request looks for the service closest to the local IP address. - 匹配的对等方名称可以在本地或远程注册,但解析请求会查找最接近本地 IP 地址的服务。
NearestRemotePeerName - NearestRemotePeerName   The resolve request excludes any peer name registered locally on this computer and looks for the service closest to the local IP address. - 解析请求会排除在此计算机上本地注册的任何对等方名称,并查找最接近本地 IP 地址的服务。
NonCurrentProcessPeerName - NonCurrentProcessPeerName   The matching peer name can be registered locally or remotely, but the resolve request excludes any peer name registered by the process making the resolve request. - 匹配的对等方名称可以在本地或远程注册,但解析请求会排除进行解析请求的进程注册的任何对等方名称。
RemotePeerName - RemotePeerName   The resolve request excludes any peer name registered locally on this computer. - 解析请求会排除在此计算机上本地注册的任何对等方名称。

Again, a series of Windows Socket calls are used to synchronously begin a lookup. - 同样,一系列 Windows Socket 调用用于同步开始查找。

  • Call WSALookupServiceBegin to begin the enumeration and return a handle. - 调用 WSALookupServiceBegin 开始枚举并返回句柄。
  • Call WSALookupServiceNext to resolve the peer name. - 调用 WSALookupServiceNext 来解析对等方名称。
  • Call WSALookupServiceEnd to complete the enumeration. - 调用 WSALookupServiceEnd 来完成枚举。

The following code shows this - 以下代码显示了这一点

public static bool Lookup(PeerRegistration Registration)
{
    PNRPINFO pnrpInfo = new PNRPINFO();
    BLOB blPnrpData = new BLOB();
    WSAQUERYSET querySet = new WSAQUERYSET();
    
    pnrpInfo.dwSize = Marshal.SizeOf(typeof(PNRPINFO));
    pnrpInfo.nMaxResolve = 1;
    pnrpInfo.dwTimeout = 30;
    pnrpInfo.enResolveCriteria = Registration.Criteria;
    
    blPnrpData.cbSize = Marshal.SizeOf(typeof(PNRPINFO));
    blPnrpData.pBlobData = Marshal.AllocHGlobal(blPnrpData.cbSize);
    Marshal.StructureToPtr(pnrpInfo, blPnrpData.pBlobData, false);
    
    querySet.dwSize = Marshal.SizeOf(typeof(WSAQUERYSET));
    querySet.dwNameSpace = 38; // NS_PNRPNAME
    querySet.lpServiceClassId = 
          Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
    Marshal.StructureToPtr(SVCID_PNRPNAMEV1, 
            querySet.lpServiceClassId, false);
    querySet.lpszServiceInstanceName = Registration.PeerName;
    if (Registration.CloudName != string.Empty)
        querySet.lpszContext = 
            Marshal.StringToHGlobalUni(Registration.CloudName);

    querySet.lpBlob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BLOB)));
    Marshal.StructureToPtr(blPnrpData, querySet.lpBlob, false);
    
    IntPtr qryptr = 
           Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WSAQUERYSET)));
    Marshal.StructureToPtr(querySet, qryptr, false);
    
    IntPtr hLookup;
    int err = PnrpNative.WSALookupServiceBegin(qryptr, 
              WSALookup.LUP_RETURN_NAME | WSALookup.LUP_RETURN_ADDR | 
              WSALookup.LUP_RETURN_COMMENT, out hLookup);
    if (err != 0)
     throw new 
       System.Net.Sockets.SocketException(PnrpNative.WSAGetLastError());

    IntPtr pResults;
    err = LookupServiceNext(hLookup, out pResults);
    
    bool found = false;
    if (err == 0)
    {
        querySet = (WSAQUERYSET)Marshal.PtrToStructure(pResults, 
                                           typeof(WSAQUERYSET));
        CSADDR_INFO csaAddr = (CSADDR_INFO)
                Marshal.PtrToStructure(querySet.lpcsaBuffer, 
                typeof(CSADDR_INFO));
        // return the first IPv6 address found
        for (int i = 0; i < querySet.dwNumberOfCsAddrs; i++)
        {
            if (csaAddr.iProtocol == (int)System.Net.Sockets.ProtocolType.Tcp 
                && csaAddr.RemoteAddr.iSockaddrLength == 
                Marshal.SizeOf(typeof(SOCKADDR_IN6)))
            {
                SOCKADDR_IN6 addr = (SOCKADDR_IN6)
                    Marshal.PtrToStructure(csaAddr.RemoteAddr.lpSockaddr, 
                    typeof(SOCKADDR_IN6));
                Registration.Address = new System.Net.IPEndPoint(new 
                    System.Net.IPAddress(addr.sin6_addr), addr.sin6_port);
                found = true;
                break;
            }
        }
        Marshal.FreeHGlobal(pResults);
    }

    PnrpNative.WSALookupServiceEnd(hLookup);
    return found;
}

DNS Name Corresponding to a Peer Name - 与对等方名称对应的 DNS 名称

Since PNRP is a serverless DNS, it makes sense to be able to lookup the DNS name associated with a Peer Name. It's also useful to determine the Peer Name given a DNS name. Starting in Windows Vista, two additional Peer-to-Peer APIs are provided to do just this. The code below shows calling these functions from C# - 由于 PNRP 是无服务器 DNS,因此能够查找与 Peer Name 关联的 DNS 名称是有意义的。给定 DNS 名称来确定 Peer Name 也很有用。从 Windows Vista 开始,提供了两个额外的对等网络 API 来执行此操作。以下代码显示了如何从 C# 调用这些函数

public static string PnrpToDns(string PnrpName)
{
    int length = 255;
    System.Text.StringBuilder DnsName = 
                   new System.Text.StringBuilder(length);
    int err = PnrpNative.PeerNameToPeerHostName(PnrpName, 
                                    DnsName, ref length);
    if (err != 0)
        throw new System.Net.Sockets.SocketException(err);
    return DnsName.ToString();
}

public static string DnsToPnrp(string DnsName)
{
    int length = 255;
    System.Text.StringBuilder PnrpName = 
           new System.Text.StringBuilder(255);
    int err = PnrpNative.PeerHostNameToPeerName(DnsName, 
                                  PnrpName, ref length);
    if (err != 0)
        throw new System.Net.Sockets.SocketException(err);
    return PnrpName.ToString();
}

关注点

Now that you've seen the gory details of using the WSAxx functions to interact with PNRP, you'll be glad to know that Microsoft will be providing wrapper functions to hide these details. These wrapper functions will be available for Windows Vista Beta 2 and later. I can only guess that these functions will also be available in Windows XP Service Pack 3. While there is currently no documentation for these functions, I've taken a guess at their purpose. - 现在您已经看到了使用 WSAxx 函数与 PNRP 交互的详细信息,您会很高兴知道 Microsoft 将提供包装函数来隐藏这些详细信息。这些包装函数将适用于 Windows Vista Beta 2 及更高版本。我只能猜测这些函数也将适用于 Windows XP Service Pack 3。虽然目前还没有这些函数的文档,但我已经猜测了它们的作用。

  • PeerPnrpGetCloudInfo - returns an array of PNRPCLOUDINFO structures matching the given scope. - PeerPnrpGetCloudInfo - 返回与给定范围匹配的 PNRPCLOUDINFO 结构数组。
  • PeerPnrpGetEndpoint - lookup a peer name to get its address. - PeerPnrpGetEndpoint - 查找对等方名称以获取其地址。
  • PeerPnrpRegister, PeerPnrpUnregister - register and unregister a peer name. - PeerPnrpRegister, PeerPnrpUnregister - 注册和注销对等方名称。
  • PeerPnrpUpdateRegistration - allows info such as address and comment to be updated for a previously registered peer name. - PeerPnrpUpdateRegistration - 允许更新先前注册的对等方名称的地址和注释等信息。
  • PeerPnrpResolve - synchronously lookup if a peer name exists. - PeerPnrpResolve - 同步查找对等方名称是否存在。
  • PeerPnrpStartResolve, PeerPnrpEndResolve - asynchronously lookup a peer name. - PeerPnrpStartResolve, PeerPnrpEndResolve - 异步查找对等方名称。

资源链接

I have found the following resources to be very useful in understanding Microsoft's Peer-to-Peer technology - 我发现以下资源对于理解 Microsoft 的对等网络技术非常有帮助

结论

I hope you have found this article as a useful starting point. I'm considering writing more articles on the following subjects to further your understanding of Microsoft's Peer-to-Peer technology - 我希望您认为本文是一个有用的起点。我正在考虑撰写关于以下主题的更多文章,以进一步您对 Microsoft 对等网络技术的理解

  1. Peer Name Resolution - netsh. - 对等方名称解析 - netsh。
  1. Peer Graph - The Basics - 对等方图 - 基础知识
  2. 对等图形 - 节点和连接
  3. 对等图形 - 记录
  4. 对等图形 - 属性
  5. 对等图形 - 搜索
  1. 对等组和身份
  1. 对等协作 - 附近的人
  2. 对等协作 - 端点
  3. 对等协作 - 能力
  4. 对等协作 - 在线状态
  5. 对等协作 - 邀请

If you have suggestions or other topics, please leave a comment. Oh! and don't forget to vote. - 如果您有建议或其他主题,请留言。哦!别忘了投票。

历史

  • 初始版本。
© . All rights reserved.