Windowsライブラリを使用してNATの外部IPアドレスを取得するにはどうすればよいですか?INATExternalIPAddressCallbackに関する情報を見つけようとしていますが、C#への使用できないインターフェイスを使用したC++の例は1つしか見つかりませんでした。任意のガイダンスをいただければ幸いです。
-カール
申し訳ありませんが、UPNP サービスを使用する Windows の既存の API についてはお答えできませんが、参考になるかもしれません。
インターネット上で STUN サーバーを使用することもできます。多くのオープン サーバーがあり、すべての VOIP プロバイダーに 1 つあります。 http://en.wikipedia.org/wiki/STUN https://www.rfc-editor.org/rfc/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 アドレスは、外部から見た場合の IP アドレスである必要があります。
インターネットサーバーの助けがなければ、またはサーバーから直接upnp経由で外部IPを取得できないことに注意してください
NAT の背後にあるシステムは、それが「実際の」IP であることを知りません。実際、OSに関する限り、他のOSと同様にIPを持っています。定義されたゲートウェイにルーティングするだけで、詳細を気にする必要はありません。構成された IP がブロードキャスト アドレス (10.whatever、192.168.whatever) ではないという事実は、OS にとって重要ではありません。
外部 IP を取得する唯一の方法は、外部システムにクエリを実行することです。それはあなたのUPnPルーターかもしれません(理論的には、さらに別の非ブロードキャストアドレスを返す可能性があります)、またはインターネット上の外部サーバーかもしれません(たとえば、この「STUN」のもの)。
私だったら、自分のウェブサイトで自分のサービスをホストするだけです。ほとんどの PHP 対応 Web サイトで、単純な php スクリプトを実行するだけです。
<?php echo $REMOTE_ADDR; >
これにより、クライアントの IP アドレスがキックバックされます。次に、そのスクリプトの結果を取得するクライアント コードを作成する必要があります (C# ではかなり簡単です)。
CodeProject では、harold aptroot による次の記事で、何をしたいのかを説明しています。
ライブラリなしで、C# の UPnP を使用した NAT トラバーサル。 http://www.codeproject.com/KB/IP/upnpnattraversal.aspx
もちろん、これはルーターが UPnP をサポートしている場合にのみ機能します。
MSDN から -- http://msdn.microsoft.com/en-us/library/aa365074(VS.85).aspx :
INATExternalIPAddressCallback インターフェイスは、UPnP テクノロジを使用する NAT アプリケーションによって実装されます。これは、NAT コンピュータの外部 IP アドレスが変更された場合にシステムが呼び出すメソッドを提供します。
一度外部 IP アドレスを取得しようとしていますか、それとも変更された場合に通知を受け取りたいですか。現在の外部 IP アドレスを取得するだけの場合は、INATExternalIPAddressCallback のコールバックを実装する必要はありません。