名前は似ているが別物のWebSocket
「WebSocket」は名前こそ似ていますが、このページで説明したOSレベルのソケットとは別物で、ブラウザとサーバーが持続的に双方向通信を行うために作られた、独立したアプリケーション層のプロトコルです。WebSocketの接続自体は、内部的には通常のTCPソケットの上に構築されています。
ソケット・ファイアウォール・ポートフォワーディングは同じ考え方の別の側面
ファイアウォールが特定のポートをブロックするというのは、実際にはそのポートで新しいソケットが作られるのを防いでいるということであり、ポートフォワーディングはルーターに届いたソケット接続をネットワーク内の特定の機器に転送する仕組みです。ソケットの概念が腑に落ちると、これらの関連する用語が別々に覚えるべきルールではなく、つながった一つの仕組みだと見えてきます。
netstatやssの出力の読み方
Windowsではnetstat -an、Linuxではss -tanを実行すると、ローカルアドレス、リモートアドレス、状態を持つソケットの一覧が表示されます。状態がLISTENの行はリスニングソケットで、サーバーが待ち受けているアドレスを示します。0.0.0.0や[::]はすべてのインターフェースで待ち受けていることを、127.0.0.1はそのマシン内だけで待ち受けていることを意味します。ESTABLISHEDの行は進行中の会話で、それぞれがローカルとリモートの端点の固有の組み合わせです。TIME_WAITやCLOSE_WAITは接続の終了処理中を示します。1つのプログラムが持つCLOSE_WAITが大量にある場合は、そのプログラムが接続を正しく閉じていない、サーバーコードによくあるバグの可能性があります。こうした状態を知っておくと、サービスがそもそも待ち受けているかどうかを判断しやすくなり、つながらないときに最初に確認すべき点が分かります。
ソケットを扱うときのよくある間違い
初心者は、接続の失敗とポートが閉じていることを混同しがちです。接続拒否は、マシンが応答したがそこで待ち受けているものがなかったことを意味し、タイムアウトはファイアウォールがパケットを捨てたか、ホストに到達できないことを意味するのが普通です。また、サーバーを127.0.0.1にバインドしたため他のマシンから届かない、という落とし穴もあります。TCPはメッセージではなくバイトの流れだということを忘れると、1回の送信が2回の受信に分かれたり、2回の送信が1回にまとまって届くバグが起きます。さらに、ポートが使用中というエラーは、別のプログラムか、前回の実行によるTIME_WAITがそのアドレスを保持していることがほとんどです。
よくある質問
ソケット番号は自分で決める必要がありますか?
いいえ。サーバー側のウェルノウンポート(80番や443番など)はプログラムや管理者が指定しますが、クライアントとして使う一時ポートはOSが自動的に割り当てるため、利用者が設定する必要はありません。
サーバーでソケットが足りなくなることはありますか?
はい。非常に短い時間に大量の接続の確立と切断を繰り返すサーバーでは、一時ポートが一時的に不足する「ソケット枯渇」と呼ばれる現象が起こることがあります。この場合、サーバー側の接続の再利用(キープアライブ)設定を調整することで緩和されることがあります。
1台の機器にポートはいくつありますか?
TCPとUDPそれぞれに65,536個(0〜65535)の番号があります。0番は予約されており通常の通信には使われません。実際にはすべてを使うわけではなく、大半はその時点で使われていません。
2つのプログラムが同じポートで待ち受けることはできますか?
同じアドレスとプロトコルでは通常はできず、後から起動したほうがアドレス使用中のエラーになります。負荷分散のために複数のプロセスが同じポートで受け付けるオプションもありますが、明示的に有効にする必要があります。TCPとUDPはポートの空間が別なので、一方のプログラムがTCPの53番、別のプログラムがUDPの53番を使うことは可能です。
ソケットとコネクションは同じものですか?
近いものですが同一ではありません。ソケットはプログラムが持つ片方の端点で、コネクションは2つの端点の組み合わせです。リスニングソケットは、クライアントが来るまでコネクションを持ちません。