C#에서 inatexternalipaddresscallback을 사용하여 NAT의 외부 iPaddress를 얻으려고합니다.

StackOverflow https://stackoverflow.com/questions/799557

  •  18-09-2019
  •  | 
  •  

문제

Windows 라이브러리를 사용하여 NAT의 외부 IP 주소를 어떻게 얻습니까? inatexternalipaddresscallback에 대한 정보를 찾으려고 노력하고 있지만 C#에 사용할 수없는 인터페이스를 사용하여 C ++에서 한 예제 만 발견했습니다. 모든 지침은 대단히 감사 할 것입니다.

-Karl

도움이 되었습니까?

해결책

죄송합니다. UPNP 서비스를 사용하는 Windows의 기존 API로 대답하지 않지만 도움이됩니다.

인터넷에서 기절-서버를 사용할 수도 있고, 열린 개방형이 많이 있으며, 모든 VoIP 제공 업체에는 하나가 있습니다.http://en.wikipedia.org/wiki/stun http://tools.ietf.org/html/rfc3489

예를 들어 UDP 소켓을 열고 포트 3478에서 stun.gmx.net에 연결하고 다음과 같은 파켓을 보내십시오.

using System;
using System.Net;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace xxx
{
class STUNPacket
{
    static RNGCryptoServiceProvider m_rand=new RNGCryptoServiceProvider();

    private byte[] m_requestid=new byte[16];

    public STUNPacket()
    {
        m_rand.GetBytes(m_requestid);
    }

    public byte[] CreateRequest()
    {
        byte[] packet=new byte[0x1c] {
            //Header:
            0x00,0x01,      //Art des STUN-Pakets: 0x0001=Binding Request
            0x00,0x08,      //Länge des Pakets ohne Header
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    //Transkations-ID
            //Message-Attribute:
            0x00,0x03,      //Typ: Change-Request
            0x00,0x04,      //Länge: 4 Bytes
            0x00,0x00,0x00,0x00 //Weder IP, noch Port ändern
        };

        for(int i=0;i<16;i++)
            packet[i+4]=m_requestid[i];

        return packet;
    }

    public IPEndPoint ParseResponse(byte[] paket)
    {
        if (paket.Length<20)
            throw new Exception("STUN-Response zu kurz, um einen Header zu haben");
        if (paket[0]!=1||paket[1]!=1)
            throw new Exception("STUN-Reposne hat falschen Typ, muss Binding-Response sein");
        for (int i=0;i<16;i++)
            if (paket[i+4]!=m_requestid[i])
                throw new Exception("STUN-Antwort hat falsche Transkations-ID");
        int size=paket[2]*256+paket[3];
        int pos=20;
        for(;;)
        {
            if (size<4)
                throw new Exception("Verbleibende Nachricht zu kurz für weiteren Attributheader, "+
                    "Mapped-Adress-Attribut nicht gefunden");
            int attrsize=paket[pos+2]*256+paket[pos+3];
            if (pos+4+attrsize>paket.Length)
                throw new Exception("Attributheader hat Länge, die nicht mehr ins Paket passt");
            //Wenn kein Mapped-Adress-Attribut, dann überspringen
            if (paket[pos]!=0||paket[pos+1]!=1)
            {
                pos+=attrsize;
                continue;
            }
            if (attrsize<8)
                throw new Exception("Mapped-Adress-Attribut ist zu kurz");
            if (paket[pos+5]!=1)
                throw new Exception("Adreßfamilie von Mapped-Adress ist nicht IPV4");
            int port=paket[pos+6]*256+paket[pos+7];
            IPAddress adress=new IPAddress(new byte[4] { paket[pos+8],paket[pos+9],paket[pos+10],paket[pos+11] });
            return new IPEndPoint(adress,port);
        }
    }

}

}

Parseresponse가 반환 한 IP-Address는 외부 세계가 보는 것처럼 IP 주소 여야합니다.

인터넷 서버의 도움없이 또는 서버에서 UPNP를 통해 직접 외부 IP를 얻을 수 없습니다.

다른 팁

CodeProject에서 Harold Aptroot의 다음 기사는 다음과 같은 사항을 설명합니다.

라이브러리가없는 C#에서 UPNP를 사용하여 Nat Traversal.http://www.codeproject.com/kb/ip/upnpnattraversal.aspx

코스 오프 코스 이것은 라우터가 UPNP를 지원하는 경우에만 작동합니다.

MSDN에서 - http://msdn.microsoft.com/en-us/library/a365074(vs.85).aspx:

inatexternalipaddresscallback 인터페이스는 UPNP 기술을 갖춘 NAT 응용 프로그램에 의해 구현됩니다. NAT 컴퓨터의 외부 IP 주소 인 경우 시스템이 호출하는 방법을 제공합니다. 변화.

외부 IP 주소를 한 번 받으려고합니까, 아니면 변경되면 알림을 받으려고합니까? 현재 외부 IP 주소를 얻으려면 inatexternalipaddresscallback에 대한 콜백을 구현할 필요가 없습니다.

NAT 뒤에있는 시스템은 그것이 "실제"IP인지 알지 못합니다. 실제로 OS에 관한 한, 다른 IP와 같은 IP가 있습니다. 그것은 단순히 정의 된 게이트웨이로 나가며 세부 사항에 대해 걱정할 필요가 없습니다. IP 구성이 브로드 캐스트 주소가 아니라는 사실은 OS에 중요하지 않습니다.

외부 IP를 얻는 유일한 방법은 외부 시스템을 쿼리하는 것입니다. UPNP 라우터 (Thoery에서는 다른 비 브로드 캐스트 주소를 반환 할 수 있음) 일 수도 있고 인터넷의 외부 서버 (예를 들어이 "Stun"이 될 수 있음) 일 수 있습니다.

그것이 나라면, 나는 단지 내 웹 사이트에서 내 서비스를 주최합니다. 대부분의 PHP 가능 웹 사이트에서 간단한 PHP 스크립트를 버릴 수 있습니다.

<?php echo $REMOTE_ADDR; >

클라이언트의 IP 주소를 다시 시작합니다. 다음으로 해당 스크립트의 결과를 가져 오려면 클라이언트 코드를 작성해야합니다 (C#에서는 쉽게 쉽게).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top