山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他Wake On Lan パケット送信プログラム
概要
Wake On Lanは、電源が切れている機器にマジックパケットを送信し電源を入れる規格である。
本プログラムは、LAN内に対してはブロードキャストアドレスとMACアドレスを指定することによりマジックパケットを送信する。
MACアドレスとは、ベンダー名が上位3オクテットで下位3オクテットが重複しない番号となっている。
WANに対してはグローバルIPアドレスとポート番号、MACアドレスを指定することによりマジックパケットを送信する。WANを使用する場合、ルータがWAN側からの指定されているLANのIPアドレスのポートへパケットを通すような設定にしなければなりません。うまく動かないことが多いようです。また電源が入っていない機器はブロードキャストに反応しませんので、ルータのARPキャッシュが時間が経過し消えればできなくなります。Wake On LAN対応のルーターが必要です。
本プログラムを実行するパソコンのIPアドレスが192.168.0.1、ネットマスクが255.255.255.0の場合、
まずそれぞれを16進数に直すと、0xc0,0xa8,0x00,0x01、0xff,0xff,0xff,0
2進数では、以下の通りとなります。
本プログラムは、LAN内に対してはブロードキャストアドレスとMACアドレスを指定することによりマジックパケットを送信する。
MACアドレスとは、ベンダー名が上位3オクテットで下位3オクテットが重複しない番号となっている。
WANに対してはグローバルIPアドレスとポート番号、MACアドレスを指定することによりマジックパケットを送信する。WANを使用する場合、ルータがWAN側からの指定されているLANのIPアドレスのポートへパケットを通すような設定にしなければなりません。うまく動かないことが多いようです。また電源が入っていない機器はブロードキャストに反応しませんので、ルータのARPキャッシュが時間が経過し消えればできなくなります。Wake On LAN対応のルーターが必要です。
マジックパケットの概要
マジックパケットは、0xffを6回送信後、MACアドレスを16回送信することで作成できます。ブロードキャストアドレス
電源が入っていない機器であるためIPアドレスは確定していない。よって、ブロードキャストアドレスを用いる。本プログラムを実行するパソコンのIPアドレスが192.168.0.1、ネットマスクが255.255.255.0の場合、
まずそれぞれを16進数に直すと、0xc0,0xa8,0x00,0x01、0xff,0xff,0xff,0
2進数では、以下の通りとなります。
IP 11000000 10101000 00000000 00000001
MASK 11111111 11111111 11111111 00000000
MASKを反転させIPと論理和を求めるとブロードキャストアドレスが得られます。
IP & MASK 11000000 10101000 00000000 00000000
~MASK 00000000 00000000 00000000 11111111
IP | ~MASK 11000000 10101000 00000000 11111111
192.168.0.255
プログラムを使用するには、ソースファイルに記述されているIPアドレスとMACアドレスを修正してコンパイルしてください。
テスト環境
コンパイラ
Visual C++ 2008 Standard 32/64bitVisual C++ 2013 Express 32/64bit
実行環境
マジックパケット送信側
Windows 8.1 Enterprise 64bit Windows 7 EnterPrise Service Pack 1 64bitWindows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit
マジックパケット受信側
IO-DATA RECBOXプログラムソースの概要
グロバール変数macにMACアドレス、グロバール変数ipにブロードキャストアドレスを設定します。
例えばMACアドレス 34:76:c5:12:34:56、IPアドレス192.168.0.255の場合、以下のように設定します。
WSAStartup関数を呼び出しWinsockを初期化します。
TransMagicPacket関数を呼び出しマジックパケットを送信します。
WSACleanup関数でWinsockを解放します。
packet配列の先頭から6個分、0xffで初期化します。
memcopy関数でmacアドレスを6回、packet配列にコピーします。
socket関数でUDPソケットを指定します。
SOCKADDR_IN構造体にアドレスとポート等を設定します。
sendto関数でpacket配列を送信します。
closesocket関数でソケットを閉じます。
例えばMACアドレス 34:76:c5:12:34:56、IPアドレス192.168.0.255の場合、以下のように設定します。
BYTE mac[6] = { 0x34, 0x76, 0xc5, 0x12, 0x34, 0x56 };
BYTE ip[4] = { 192, 168, 0, 255 };
_tWinMain関数
Windowsから最初に_tWinain関数が呼び出されます。WSAStartup関数を呼び出しWinsockを初期化します。
TransMagicPacket関数を呼び出しマジックパケットを送信します。
WSACleanup関数でWinsockを解放します。
TransMagicPacket関数
パケットサイズは、6+6*19=102バイトですので、BYTE型の102バイトの配列packetを作成します。packet配列の先頭から6個分、0xffで初期化します。
memcopy関数でmacアドレスを6回、packet配列にコピーします。
socket関数でUDPソケットを指定します。
SOCKADDR_IN構造体にアドレスとポート等を設定します。
sendto関数でpacket配列を送信します。
closesocket関数でソケットを閉じます。
プログラムソース
// Wake On Lan テストプログラム // Visual C++ 2008/2013 32/64bit #include <windows.h> #include <tchar.h> #pragma comment(lib,"Ws2_32.lib") BYTE mac[6] = { 0x34, 0x76, 0xc5, 0x12, 0x34, 0x56 }; // MACアドレスの設定 BYTE ip[4] = { 192, 168, 0, 255 }; // ブロードキャストアドレスの設定 // マジックパケットを送信 BOOL TransMagicPacket(DWORD addr, int port, BYTE *mac); int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* CmdLine, int nCmdShow){ WSADATA wsaData; // WinSockの初期化 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) return 0; // マジックパケットの送信 DWORD ipa = *(DWORD*)ip; TransMagicPacket(ipa, 0, mac); WSACleanup(); return 0; } // マジックパケットを送信 BOOL TransMagicPacket(DWORD addr, int port, BYTE *mac){ SOCKET s; SOCKADDR_IN sockadd; BYTE packet[6 + 6 * 16]; int n; // 0xFFを16回設定 for (n = 0; n<6; n++) packet[n] = 0xff; // MACアドレスを16回設定 for (n = 0; n<16; n++) memcpy(packet + 6 + n * 6, mac, 6); // UDPソケット作成 s = socket(PF_INET, SOCK_DGRAM, 0); if (s == SOCKET_ERROR) return FALSE; // ソケットアドレスの設定 sockadd.sin_family = AF_INET; sockadd.sin_addr.s_addr = addr; sockadd.sin_port = htons(port); // 送信 sendto(s, (LPSTR)&packet, sizeof(packet), 0, (LPSOCKADDR)&sockadd, sizeof(sockadd)); // ソケットを閉じる closesocket(s); return TRUE; }
ソースファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.