「Only one usage of each socket address」エラーを修正する — Windowsポート使用中

beginner🪟 Windows2026-03-18| Windows 10/11 — Node.js、Python、Java、.NET、またはTCPサーバーアプリケーション全般

Error Message

Only one usage of each socket address (protocol/network address/port) is normally permitted
#windows#ポート#netstat#tcp

サーバーを起動すると、Windowsが以下のエラーをスローします:

Only one usage of each socket address (protocol/network address/port) is normally permitted

これはLinuxのEADDRINUSEに相当するWindowsのエラーです。TCPポートは同時に1つのプロセスしかバインドできません — すでに別の何かがそのポートを占有しています。ポートが解放されるまで、アプリは起動できません。

原因

主に以下の3つが原因です:

  • アプリの以前のインスタンスがクラッシュまたは正常にシャットダウンされず、ポートがロックされたまま残っている
  • システムサービス(IIS、SQL Server、Apache、Hyper-V仮想スイッチ)がWindows起動時にポートを取得した
  • Windows自身がポート範囲を予約した — Hyper-V、WSL2、Docker Desktopを有効にした後に発生することがある

手順1:ポートを使用しているプロセスを特定する

管理者としてコマンドプロンプトを開き、以下を実行します:

netstat -ano | findstr :3000

3000を実際のポート番号に置き換えてください。出力は以下のようになります:

  TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       12345

最後の列がPID(プロセスID)です。そのPIDに対応するプログラムを確認するには:

tasklist /FI "PID eq 12345"

出力例:

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
node.exe                     12345 Console                    1     52,340 K

これでポートを占有しているプロセスが正確にわかります。

手順2:プロセスを終了する

taskkill /PID 12345 /F

/Fフラグは強制的に即時終了させます。アクセスが拒否されましたと表示される場合は、昇格されたプロンプトが必要です — スタートメニューを右クリックして**Windows Terminal(管理者)またはコマンドプロンプト(管理者)**を選択してください。

PowerShellのワンライナー

PowerShellを使用する場合は、以下の1行でプロセスを検索して終了できます:

Stop-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess -Force

終了する前に対象プロセスを確認したい場合:

Get-NetTCPConnection -LocalPort 3000 | Select-Object LocalPort, OwningProcess,
  @{n='ProcessName'; e={(Get-Process -Id $_.OwningProcess).Name}}

出力例:

LocalPort OwningProcess ProcessName
--------- ------------- -----------
     3000         12345 node

特殊ケース:Windowsの予約済みポート範囲

Hyper-V、WSL2、Docker Desktopを有効にすると、Windowsは起動時に動的ポートのブロックを予約します。ポートが予約済みブロック内にある場合、プロセスを終了しても解決しません — OSがネットワークスタックレベルでブロックしているためです。

Windowsが予約しているポートを確認するには:

netsh interface ipv4 show excludedportrange protocol=tcp

出力の中に該当ポートが見つかった場合は、予約範囲外のポートに切り替えてください。または、動的ポート範囲をリセットすることもできます:

netsh int ipv4 set dynamicport tcp start=49152 num=16384

変更後はWindowsを再起動してください。注意点として、Hyper-VとDockerは49152〜65535の範囲だけでなく、5000〜9000の範囲のブロックも予約することがあります。ポートが空いていると仮定せず、必ず自分のマシンの実際のnetsh出力で確認してください。

手順3:修正を確認する

プロセスを終了した後、ポートが解放されたことを確認します:

netstat -ano | findstr :3000

出力がなければポートは使用可能です。サーバーを起動すれば、今度はエラーなくバインドできるはずです。

何も表示されずTIME_WAITエントリが表示される場合は?

  TCP    0.0.0.0:3000           0.0.0.0:0              TIME_WAIT       0

これは最近閉じた接続がまだ排出中の状態です。30〜60秒待ってから再試行するか、一時的に別のポートに切り替えてください。

予防策

アプリがポートを解放せずにクラッシュするために繰り返し発生する場合:

  • Node.js:終了前にHTTPサーバーを閉じるようSIGTERM/SIGINTを明示的に処理します。pm2で実行することも有効で、再起動とクリーンアップを自動的に管理します。
  • Pythonbind()を呼び出す前にソケットにSO_REUSEADDRを設定します。Flaskの開発サーバーはデフォルトでこれを行い、Gunicornも本番環境で正しく処理します。
  • Java / .NET:クラッシュ時でもポートが解放されるよう、server.close()(またはフレームワーク相当のメソッド)を呼び出すシャットダウンフックを追加します。

設定にポートをハードコードする前に、すでに使用中のポートを確認してください:

netstat -ano | findstr LISTENING

開発マシンでは、SQL Server(1433)、IIS(80/443)、PostgreSQL(5432)がバックグラウンドで静かに動いていることがよくあります。すでに使われているポートを選んでしまうと、実行時まで問題が先送りされるだけです。

Related Error Notes