ネットワーク構成を保存・復元する
なんか前にも作った気もするんだけど…
なんか前にも作った気もするんだけど…
C:\>netsh interface ipv6 show interface アクティブ状態を照会しています... Idx Met MTU State Name --- ---- ----- ------------ ----- 6 2 1280 Disconnected Teredo Tunneling Pseudo-Interface 5 0 1500 Connected ローカル エリア接続 4 0 1500 Connected ローカル エリア接続 2 3 1 1280 Connected 6to4 Pseudo-Interface 2 1 1280 Connected Automatic Tunneling Pseudo-Interface 1 0 1500 Connected Loopback Pseudo-Interface
IPv4 でマルチキャストのパケットを送出する際、デフォルトのままでは TTL が 1 になってしまう。ルータ越えの必要がある場合は以下のようにして、送信に使用するソケットのオプションを変更する。(下記は TTL を 32 に変更した例)
// #include <Winsock2.h> int ttl = 32; int result = setsockopt (socket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof ttl); if (SOCKET_ERROR == result) { // エラー処理は省略... }
C# の場合はこんなの。
// using System.Net.Sockets; int ttl = 32; socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, ttl);
でも、私が今知りたいのは、C#、つまり .NET Framework を使った方法…。3.3 - Winsock プログラム で自分の IP アドレスを取得する方法は?
3種類の方法があり、それぞれに利点、欠点があります:
- 最も簡単な方法は、connect 済みのソケットに対して getsockname() を呼び出すことです。connect 済みのソケットが無ければ、その呼出しは失敗するか、あるいは無意味な情報が返されます。
- ソケットを事前にオープンすることなしに自分のアドレスを取得するには、gethostname() の返却値に対して gethostbyname() を呼び出すことです。この例に示すように、この呼出しはそのホストが持つ全てのインターフェースのリストを返却します。 (この方式の問題点については、例のページを参照のこと。)
- 三番目の方法は Winsock 2 でのみ動作します。新しい WSAIoctl() API は SIO_GET_INTERFACE_LIST オプションをサポートしており、返却される情報の一部として、システムの各々のネットワークインターフェースのアドレスが返却されます。[C++ の例] (これも、注意点については例のページを参照のこと。)
後者二つの方式では、多くの TCP/IP ネットワークのマシンでは少なくとも二つのアドレスが返却されます。一つは「普通の」ネットワークインターフェースで、一つは「ループバック」ネットワークインターフェースになるはずです。通常、「普通の」ネットワークインターフェースはモデムかイーサネットカードです。ループバックインターフェース (IPアドレス 127.0.0.1)は、同一のマシン上で動作する二つのプログラムが、オペレーティングシステムのネットワークハードウェアレイヤを通過することなしに通信できるようにさせるものです。ループバックインターフェースを使用した通信は少なくとも普通のネットワークインターフェースと同じ程度の速度であり、ネットワークスタックによってははるかに高速になります。
一つのシステム上に二つ以上のネットワークインターフェースを持つこともあり得ます。多くのサーバでは、例えば二つ以上のネットワークインターフェースカードを持っていると、上記2番目、3番目の方法では4つ以上のエントリーが表示されます。さらに複雑な例はサテライト型インターネットルータで、これにはインターネットへの上流接続を行うモデムコネクション、インターネットからの下流接続を行うサテライトアダプタ、その他の LAN を通信するイーサネットカード、そしてもちろんループバックインターフェースが繋がっています。
もし同じマシン上で動作しているサーバとソケットを使って通信したいのであれば、ループバックインターフェースを使ってください。そうでなければ、普通のインターフェースのうちの一つを、頭をフル回転させて選ばなくてはなりません。全ての目的で使える決まりきった方法はありません。ほとんどのプログラムにおいては、実際にコネクションが使っている IP アドレスが返却されるので、上記の1の方法で十分です。もしこれが使えないのであれば、インターフェースにリストを表示して、ユーザに一つを選ばせる必要があるかもしれません。
PPPインターフェースのアドレスを知りたい、というときのように、より詳細な条件がある場合があります。この場合には上記の 3 の方式が使えます。これによって得られる情報の中には、PPP インターフェースのフラグが含まれるので、これで「ポイントto ポイント」インターフェースかどうかを知ることができるのです。
---------
2008.10.28 追記
System.Net.NetworkInformation.IPInterfaceProperties.UnicastAddresses が、Iphlpapi.dll の GetAdaptersAddresses 関数で取得できるものと同等かも。
| 8bit | 4bit | 4bit | 112bit |
| 11111111 | 00PT | XXXX | group ID |
| flags | scope |
| ビット | 値 | 意味 | 説明 | |
|---|---|---|---|---|
| 11 | P | prefix-bit | ネットワークプレフィックス埋込型アドレス | |
| 12 | T | 0 | well-known | 恒久的なマルチキャストアドレス |
| 1 | transient | 一時的なマルチキャストアドレス | ||
| 13 | XXXX | 0000(0) | reserved | |
| 0001(1) | interface-local scope | |||
| 0010(2) | link-local scope | |||
| 0011(3) | reserved | |||
| 0100(4) | admin-local scope | |||
| 0101(5) | site-local scope | |||
| 1000(8) | organization-local scope | |||
| 1110(E) | global scope | |||
| 1111(F) | reserved | |||
TCP サーバや UDP アプリなどの設定画面に登場する、バインドするネットワークアドレスを選択するコンボボックスです。はい、ものすごく限定的な Tips です。ネットワークインターフェースの列挙方法の一例、かな?
BOOL CXXXDialog::InitNetworkCombo (void)
{
char szHostName [MAX_PATH];
ZeroMemory (szHostName, sizeof szHostName);
m_ComboNetwork.Clear ();
// このコンピュータのホスト名を取得する
int nRet = gethostname (szHostName, sizeof szHostName);
if (SOCKET_ERROR == nRet)
{
// エラー処理
}
else
{
// ホスト名よりホストの情報を取得する
struct hostent* pHostEnt = gethostbyname (szHostName);
if (!pHostEnt)
{
// エラー処理
}
else
{
// INADDR_ANY を追加する
int nIndex = m_ComboNetwork.AddString (_T ("すべてのネットワーク"));
m_ComboNetwork.SetItemData (nIndex, INADDR_ANY);
// 取得したアドレスのリストをコンボボックスに追加する
for (int nCount = 0; pHostEnt->h_addr_list [nCount]; nCount ++)
{
struct in_addr Address;
memcpy (&Address, pHostEnt->h_addr_list [nCount], sizeof (struct in_addr));
nIndex = m_ComboNetwork.AddString (inet_ntoa (Address));
m_ComboNetwork.SetItemData (nIndex, Address.S_un.S_addr);
}
// ループバックを追加する
nIndex = m_ComboNetwork.AddString (_T ("127.0.0.1"));
m_ComboNetwork.SetItemData (nIndex, INADDR_LOOPBACK);
return TRUE;
}
}
return FALSE;
}
Windows2000で、192.168.1.0/24のネットワークで、
実際に使用されているIPを得るにはこんな感じで。
C:\>FOR /L %I IN (1, 1, 254) DO ping -n 1 -w 50 192.168.1.%I
C:\>ping -n 1 -w 50 192.168.1.1
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<10ms TTL=64
Ping statistics for 192.168.1.1:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
C:\>ping -n 1 -w 50 192.168.1.2
.
.
(192.168.1.1~192.168.1.254にPingを1回ずつ行います)
C:\>ARP -a >Arp.lst
C:\>
FORコマンドでPingをループさせ、
最後にARPでテキストファイルに吐き出すのがポイントです