Winsock

Winsock (Windows Sockets API, WSA) は、Windowsにおいてネットワークソフトウェアがネットワークサービス（特にTCP/IP）にアクセスする方法を定義した技術仕様である。Windows 上のTCP/IPクライアントアプリケーション（FTPクライアントや Gopherクライアント）とTCP/IPプロトコルスタックとの標準インタフェースを定義している。その名称はBSD系UNIXでプログラム間の通信に使われたソケットと呼ばれるAPIモデルに基づいている。winsock.dll というDLLファイルはWSAインタフェースの主要部分を提供するものであったため、このAPIを Winsock という略称で呼ぶことには開発者側の抵抗があったし、ユーザー側にも多くの混乱があった。ユーザーは winsock.dll さえあれば、TCP/IP プロトコルが完全にサポートされるのだと誤解していることが多かった。

背景

初期のマイクロソフトのオペレーティングシステム（MS-DOSもWindowsも）は、ネットワーク機能が貧弱で、NetBIOS/NetBEUIを主に使っていた。これは階層化されていない、ルーティング不可能なネットワーク機能であり、IBM の NetBIOS をマイクロソフトが実装したものであった。特に当時、マイクロソフトはTCP/IPを完全に無視していた。数々の大学グループ（MIT）や商用ベンダー（サン・マイクロシステムズ他）がMS-DOS用TCP/IPを開発し、ハードウェアに同梱するなどして販売していた。Windows がリリースされると、さらに Windows 向け TCP/IP を提供するベンダーが増えていった。しかし、マイクロソフトは相変わらず機能の貧弱な製品を提供していた。
これらベンダーの製品の弱点は、それぞれ独自のAPIを採用していた点である。また、メモリ使用量（当時、640KBもあれば大容量とされていた）や、複数のプロトコルを並行してサポートする方法がない点も問題だった。特に最後の問題点は重要であった。当時のネットワーク環境はベンダー毎に異なり（例えば、DECのDECnet、ノベルのNetware、Banyan Vines、IBM Lan Manager など）、それぞれ違ったプロトコルを使っていた（例えば、ノベルは IPX/SPX、IBM は NetBIOS API ベースのプロトコル、マイクロソフトは NetBEUI Frames Protocol）。従って、ユーザーが複数のネットワークサービスに接続するには、複数のブート構成を用意し、使いたいサービスに合わせて立ち上げ直して、対応するプロトコルを使えるようにする必要があった。さらにプログラミングモデルが統一されていないため、任意のベンダーのTCP/IP実装で動作するネットワークアプリケーションの開発は非常に困難であった。何らかの「標準化」が必要であることは明らかであった。
当時既にPCネットワークの分野での標準化はいくつも進められていた。アメリカ空軍の支援で行われた標準化として RFC 1001 と RFC 1002 がある。これは TCP/IP 上の NetBIOS 実装であり、NBT (NetBIOS over TCP/IP) と呼ばれた。次に FTP Software 社が中心となって進められた Crynwr packet driver がある。これは、上述したメモリ使用量の問題をアセンブリ言語で実装することで回避し、ネットワークカードの割り込みを独占しないことで複数プロトコルの同時サポート問題にも対応した。同様の試みとしてノベルのODI (Open Data-Link Interface) やマイクロソフトのNDIS (Network Driver Interface Specification) といったAPIがある。これらはTCP/IPも含めたプロトコルスタックの完全な実装ではない点が重要である。従って、例えば Crynwr の Russ Nelson が開発した QVT や WinQVT はDECのVT220端末エミュレータだが、どちらもアプリケーション内にTCP/IPスタックを持っていた。packet driver と同時に使うことが可能で、例えばノベルのIPX/SPXでNetWareのファイルサーバにアクセスすると同時に、DECのVMSにTCP/IP経由でアクセスすることが可能であった。明らかにこのような環境がこのプロジェクトの目指したものであり、例えばパリのOECDなどでそのような使われ方をしていた。
Windows Sockets API を提案したのは JSB Software の Martin Hall であり、1991年10月、CompuServeでの電子掲示板での議論が最初であった。仕様の第1版を編集したのは Martin Hall、Mark Towfiq（Microdyne、後にサン・マイクロシステムズ）、Geoff Arnold（サン・マイクロシステムズ）、Henry Sanders と J Allard（マイクロソフト）らである。著作権や知的所有権について議論があり、IETF を通すとか非営利団体を結成するといった議論がなされた。結局、単純に著作権は5人がそれぞれ所有することとなった。後に J Allard はマイクロソフト社内に大きなオフィスを与えられ、そこで ACK と NACK と名づけたイグアナを飼った。

技術

Windows Socket API 仕様は2つのインタフェースを定義している。1つはアプリケーションソフトウェア開発者が利用するAPIであり、もう1つはネットワークソフトウェア開発者が新たなプロトコルモジュールをシステムに追加する際に利用するSPIである。API は準拠アプリケーションが Winsock に準拠して実装された任意のプロトコルを使って動作可能であることを保証する。SPI は準拠プロトコルモジュールを Windows に追加可能であることと、任意のAPI準拠アプリケーションから利用可能となることを保証する。リリース当初、複数プロトコルサポートが必須だったため、このような保証は重要だったが、今では学問的興味から語られるだけである。Windows Socket version 2.0 には IPX/SPX で使われる機能も含まれているが、Winsock 2.0 リリース当時から既に廃れつつあるプロトコルであり、今ではこれを使うものはほとんどないだろう。マイクロソフトは最近の Windows には必ず高品質なTCP/IPスタックを実装しており、その代替となる有力な製品も存在しない。さらに言えば、TCP/IP 以外のプロトコルを実装しなければならない強い動機も存在しない。
Windows Sockets はバークレーのソケットに基づいているが、Windows の標準プログラミングモデルに対応するために機能を追加している。Winsock はソケットのほとんどの機能をカバーしているが、Windows と UNIX の根本的な違いからどうしても避けられない差異も生じている（とは言っても、STREAMSとの差異に比べれば、ずっとソケットに近い）。APIに含まれる全ての関数名の頭にはWSAが付く。例えばホスト名参照の WSAGetHostByName() などである。BSDソケットからの拡張で特筆すべきは、「ノンブロッキング」（非同期）ソケットである（通常の関数名の前に WSAAsync を付け、WSAAsyncGetHostByName() などとする）。
設計目標は、UNIXから Windows へのソケットベースのアプリケーションの移植を容易にすることであった。新たに Windows 向けに書かれるプログラムにとって、そのAPIが十分かどうかはあまり考慮されなかった。このため、Winsock には移植のために設計された要素がいくつか含まれている。例えば、UNIXアプリケーションでは、ネットワークのエラーも標準Cライブラリの関数内のエラーも同じ errno で表される。これは Windows にはない機能であるため、Winsock はそのための関数 WSAGetLastError() でエラー情報が得られるようにした。このような機能は役立つものの、アプリケーションの移植はなかなか困難だった。多くのTCP/IPアプリケーションは、仮想端末とかforkシステムコールといったUNIXのシステム固有機能を使って実装されており、そのような機能を Windows で再現するのが困難だったのである。しかし、間もなく移植よりも Windows 独自のアプリケーション開発の方が主流となっていった。