winsockの初期化

ここでは、winsockの初期化と終了処理の説明を行いたいと思います。

WSAStartup、WSACleanup

winsock機能を利用する前には必ずwinsockの初期化を行わなければいけません。 winsockの初期化はWSAStartup()を利用して行います。 WSAStartup()は一度だけ行えば大丈夫です。

winsock機能を終了するには、WSACleanup()を使います。 WSACleanup()はプログラムの最後や終了処理の中で行うのが一般的です。

以下にwinsockの初期化と終了のみを行ったコードを示します。


#include <winsock2.h>

int
main()
{
 WSADATA wsaData;

 WSAStartup(MAKEWORD(2,0), &wsaData);

 WSACleanup();

 return 0;
}

WSAStartup()は2つの引数を取ります。 一つ目の引数ではwinsockのバージョンを指定します。 2004/12現在、指定できるバージョンには、1.0、1.1、2.0の三種類があります。 ここでは、2.0を使う物とします。

サンプルでは、MAKEWORD(2,0)を第一引数としてWSAStartup()に渡しています。 WSAStartup()の第一引数はWORDです。 WORDは16ビットの符号なし変数です。 WSAStartup()では、WORDの16ビットのうち8ビットにメジャー番号、残り8ビットにマイナー番号を入れて引数として渡さないといけません。 MAKEWORD()は、2つの引数をWORDにpackするマクロです。

WSAStartup()の2つ目の引数は、WSAStartup()が初期化した状態を入れるための変数を渡します。 WSAStartup()は、初期化を行うと渡されたWSADATA構造体にwinsockのバージョンなどの情報を代入します。

エラーの取得

WSAStartup()が失敗することもあります。 WSAStartup()が失敗すると、それ以降のwinsock機能は全て失敗してしまうので、WSAStartup()のエラー処理は非常に重要です。 WSAStartup()が成功した場合、WSAStartup()は0を返します。 それ以外の値が返された場合には、初期化に失敗しています。 WSAStartup()のエラー処理例を以下に示します。


#include <stdio.h>
#include <winsock2.h>

int
main()
{
 WSADATA wsaData;
 int err;

 err = WSAStartup(MAKEWORD(2,0), &wsaData);
 if (err != 0) {
	switch (err) {
		case WSASYSNOTREADY:
			printf("WSASYSNOTREADY\n");
			break;
		case WSAVERNOTSUPPORTED:
			printf("WSAVERNOTSUPPORTED\n");
			break;
		case WSAEINPROGRESS:
			printf("WSAEINPROGRESS\n");
			break;
		case WSAEPROCLIM:
			printf("WSAEPROCLIM\n");
			break;
		case WSAEFAULT:
			printf("WSAEFAULT\n");
			break;
	}
 }

 WSACleanup();

 return 0;
}

それぞれのエラーの意味を以下に示します。

WSASYSNOTREADY ネットワークサブシステムがネットワークへの接続を準備できていない
WSAVERNOTSUPPORTED 要求されたwinsockのバージョンがサポートされていない
WSAEINPROGRESS ブロッキング操作の実行中であるか、 またはサービスプロバイダがコールバック関数を処理している
WSAEPROCLIM winsockが処理できる最大プロセス数に達した
WSAEFAULT 第二引数であるlpWSAData は有効なポインタではない

上記例のように何故失敗したかを全て詳細に書く必要は必ずしもありませんが、WSAStartup()が成功したか失敗したかは必ず確認するようにしましょう。

プロフェッショナルIPv6解説動画シリーズ再生リスト

動画で学ぶ「プロフェッショナルIPv6」を作っています。 もしよろしければご覧ください。お楽しみいただければ幸いです!