問題概要
Hyper-Vを有効化したWindows環境において、特定のネットワークポートがシステム予約領域に含まれるため、アプリケーションがポート使用時にエラーを発生させる事象が確認されています。特にIPC通信の確立時にポートリッスンに失敗する症状が報告されています。
診断手順
netstat -ano | findstr [ポート番号]でポート使用状況を確認しても、該当ポートは空き状態に表示される- ポート検出ロジックのコードレビューで、アクティブな接続検知機能に問題なしと確認済み
bool CheckPortAvailability(int port) {
var props = IPGlobalProperties.GetIPGlobalProperties();
return props.GetActiveTcpListeners().Any(p => p.Port == port) ||
props.GetActiveUdpListeners().Any(p => p.Port == port) ||
props.GetActiveTcpConnections().Any(c => c.LocalEndPoint.Port == port);
}
根本原因
Hyper-Vの有効化により、netsh int ipv4 show excludedportrange protocol=tcpコマンドで確認できるように、複数のポート範囲がシステム予約領域として除外されていることが判明。この予約領域内のポートは、プロセス未使用状態であっても実際には使用不可となる。
解決策
一時的措置(管理者権限必要)
net stop winnat
net start winnat
永続的設定変更(再起動必要)
netsh int ipv4 set dynamic tcp start=49152 num=16384
netsh int ipv6 set dynamic tcp start=49152 num=16384
コードレベルでの回避策
システム予約ポート範囲を取得し、ポート選定時にその範囲を除外する実装例:
class PortManager {
public int BasePort { get; set; } = 18743;
public int FindAvailablePort() {
var reservedRanges = GetReservedPortRanges();
for (int i = 0; i < 10000; i++) {
int candidate = BasePort + i;
if (candidate >= 65535) return 0;
if (!IsPortReserved(candidate, reservedRanges) &&
!CheckPortAvailability(candidate)) {
return candidate;
}
}
return 0;
}
List<PortRange> GetReservedPortRanges() {
// netshコマンド実行と出力解析ロジック
var ranges = new List<PortRange>();
var process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "netsh.exe",
Arguments = "int ipv4 show excludedportrange protocol=tcp",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
}
};
// 出力解析とPortRangeオブジェクト生成
return ranges;
}
}
動作検証例
// 使用例
var manager = new PortManager();
int availablePort = manager.FindAvailablePort();
Console.WriteLine($"確保済みポート: {availablePort}");