いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Windowsの除外ポート範囲 (10013, WSAEACCES, Socket.DoBind)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。よく忘れるのでここにメモメモ。。。。

私の周りで発生した問題だったのですが、ソケット処理で特定のポート番号でリスナー起動して接続受付する普通のプログラム作っていたが

ある日、それまで動いていたアプリが突然以下のエラーを吐きました。

System.Net.Sockets.SocketException (0x80004005): アクセス許可で禁じられた方法でソケットにアクセスしようとしました

スタックトレース見ると System.Net.Sockets.Socket.DoBind メソッドの呼び出しで発生しているので、そのまんまバインド出来ていないのは分かるのですが、このポートを利用しているプログラムなんて存在しない状態です。なので、普通に考えるとバインド出来るはず。

そういうときは、このポート番号が除外ポート範囲に入っていないかどうかを確認すると、解決する可能性が高いです。

Windowsの「除外ポート範囲」とは Hyper-VとかWSL2とかDocker Desktopなどの機能が、コンテナ間通信やNATのためにOSレベルで排他的に予約(占有)しているポート範囲のこと。

この範囲のポートはアプリケーションからBind(待受)できません。管理者権限でも無理。winnatサービスが管理しています。

今回のパターンでは、まさにこのパターンでした。最終的に「除外ポート範囲」ではない部分のポート番号に直したら動きました。

以下は、その除外ポート範囲を探す際に使えるコマンドのメモです。

ポート範囲を探すコマンド

除外ポート範囲を探す

netsh interface ipv4 show excludedportrange protocol=tcp

実行すると例えば以下のように出たりします。

プロトコル tcp ポート除外範囲

開始ポート    終了ポート
----------    --------
     50000       50059     *
     54096       54096
     63212       63311
     63312       63411
     63507       63606
     63665       63764
     63765       63864

* - 管理されている除外ポート。

この範囲のポート番号はバインド出来ません。

動的ポートの範囲を調べる

netsh int ipv4 show dynamicport tcp

大抵、以下のように出るはずです。

プロトコル tcp の動的ポートの範囲
---------------------------------
開始ポート      : 49152
ポート数        : 16384

前述した、 Hyper-VとかWSL2とかDocker Desktopなどは、この動的ポートの範囲から利用するポートブロックを確保します。

なので、開始ポートより小さいポート番号を利用するべきですね。

なので、1024 から 49151 ポートまでを使うのが安全ってことになります。つまり俗に言う「User Ports」の範囲でポート番号を使うのが安全。

(個人的には1024から9999までもあまり使いません。大抵10000以降を利用することが私の場合は多いです)

参考情報

learn.microsoft.com


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。