WinSock/初心者むけの全体像
導入の方法
[編集]基本
[編集]ウィンドウズのVisual C++などマイクロソフト製プログラミング言語を使ってネットワーク通信プログラミングをするには、Winsockをインクルードしなければならない。
なお、Winsockを使うにも、原則として Visual Studio が必要である。
まず、2020年の時点で、下記のような仕様である(実機で確認)(※ ネットにあるサイトの情報が古いので(2001年くらいのとか平気である)、2020年代の現代では実機で確認の必要がある。)。
2020年代でも、 Visual Studio でWinSockプログラミングを開発できる。
まず、Visual Studio で立ち上げるコード種類を選ぶ際には、Visual Studio の普通のC言語用のコンソールアプリケーションでよい。つまり、よく学校教育とかのC言語の授業の Hello World とかの入門で使う、普通のアレでいい。
MinGWは現状ではソケットと互換性が悪い
[編集]ネット上にはMinGWでWinSockコードをコンパイルした事例なども紹介されているが、たとえば
g++ -lwsock32 ファイル名.cpp -lws2_32
などのコマンドが各所のサイトに紹介されているが、しかし2020年現在、IPv6 関連の関数の一種である inet_pton()
や inet_ntop
など新しい関数がMinGWは対応しておらず、そのため、それらの関数を用いているコードの場合、Visual Studio コンパイルできたコードがMingWではコンパイルできない。
ちなみに、上記のg++コマンドではリンクオプションの-lを用いており、 「-lwsock32」とは「ライブラリ libwsock32 をリンクせよ」という意味。
また、コマンドラインでの -lws2_32 の位置には意味があり、コマンドラインの末尾のリンクするライブラリの指定
通信の全体像
[編集]ソケット通信は、Windowsに限らずUnixなどでも一般に、通信の工程が下記のように分類されます。
WSAなんとかという用語は Winsock だけの用語ですが、それ以外のbindやsendなどの用語は、Unixソケット通信でも共通です。
サーバー側 | クライアント側 | |
---|---|---|
ソケットの起動と初期化 | WSAStartup | WSAStartup |
↓ | ↓ | |
ソケットにアドレス登録 | bind | |
↓ | ↓ | |
クライアントからの通信待ち | listen | |
↓ | ↓ | |
クライアントがサーバに接続 | ↓ ------------------------- | connect |
受付可能の状態でサーバ待機 | accept ------------------------- | |
↓ | ↓ | |
データ送受信 | send() / receive() -------------- | send() / receive() |
↓ | ↓ | |
データ送受信の停止 | shutdown | shutdown |
↓ | ↓ | |
通信の切断 | closesocket | closesocket |
↓ | ↓ | |
ソケットの除去 | WSACleanup | WSACleanup |
コードの概要
[編集]基本骨格のコード
[編集]Winsockプログラムでの典型的な基本骨格は、下記のようになります。
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(){
WSADATA wsaData;
WSAStartup(2, &wsaData);
WSACleanup();
return 0;
}
これだけだと、単にWinsockを起動するだけなので、何も通信しないし表示しません。
このコードをもとに、これからコードをどんどん追加していって、必要なコードを加えていくことになります。
さて、Winsockでは、API関数がいくつか提供されている。
たとえば、WSAStartup
は、WinSockの初期化のための関数であり、この関数の使い方も既に決まっている。⇒ WSAStartup function (winsock.h)
なお、WSAStartup関数で必要な設定を初期化するために、事前にWSADATA 型 の変数のセットアップが必要である。
WSAStartup の1番目の変数の内容は、使用するWinsockのバージョンの指定です。とりあえず「2」を入れておけば、問題ありません(実機で確認ずみ)。
WSAStartup の2番目の変数の内容は、この処理内容を入れるためのWSADATA型変数の指定です。
なのでイメージ的には、まず
WSADATA data;
WSAStartup(バージョン指定,&data)
のように宣言をすることになる。
関数 WSACleanupは、WinSockを終了させるAPI関数です。
導入部の説明
[編集]さて、Winsockのコードは、どのコードでも、まず、
#include <winsock2.h>
のようにコードの冒頭で winsock2.h をインクルードする記述が必要になる。もう何年も前からwinsockのバージョンが 2.x なので、2020年代でも引き続き、インクルードするのは winsock2.h で良い。なお、2020年の現時点では、Winsockは普通はバージョン2.2である(実機で確認ずみ)。
また、ライブラリ 「ws2_32.lib」も必要なので、下記のように pragma 演算子でライブラリ導入する必要がある。このライブラリを導入しないと(つまり下記のpragma文が無いと)、コンパイルしようとしてビルドボタンを押してもエラーになる。
結局、
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
のように冒頭で宣言することになる(ひとまず、コレだけでも動作が可能である)。
たとえば外部リンクのウィズダムソフトのコード例も、この冒頭の宣言を加えるだけで2020年代でも動作する(実機で確認ずみ)。
なお、2020年の現時点でも、Winsockはバージョン2.2であるので、インクルードするのは <winsock2.h>
で良い。
なお、最終的にサーバ側のプログラムでも、クライアント側のプログラムでも、それぞれ <winsock2.h>
をインクルードすることになる。