針對埠耗盡問題進行疑難解答

適用於: Windows 10

TCP 和 UDP 通訊協定會根據用於建立連線的埠號碼運作。 任何需要建立 TCP/UDP 連線的應用程式或服務,在其端都需要埠。

埠有兩種類型:

  • 暫時埠是動態埠,是每部計算機默認必須建立輸出連線的埠集合。
  • 已知埠是特定應用程式或服務的定義埠。 例如,文件伺服器服務位於埠 445、HTTPS 為 443、HTTP 為 80,RPC 為 135。 自訂應用程式也會有自己的定義埠號碼。

與應用程式或服務建立連線時,用戶端裝置會使用裝置的暫時埠來連線到為該應用程式或服務定義的已知埠。 用戶端電腦上的瀏覽器會使用暫時埠連線到 https://www.microsoft.com 埠 443。

在相同瀏覽器正在建立多個網站的許多連線的情況下,對於瀏覽器嘗試的任何新連線,都會使用暫時埠。 經過一段時間之後,您會注意到連線將會開始失敗,而發生此失敗的可能性很高的原因是瀏覽器已使用所有可用的埠在外部進行連線,而任何建立連線的新嘗試都會失敗,因為沒有其他埠可用。 使用計算機上的所有埠時,我們會將其稱為埠耗盡。

TCP/IP 的預設動態埠範圍

為了符合 因特網指派號碼授權單位 (IANA) 建議,Microsoft 已增加連出連線的動態用戶端埠範圍。 新的預設啟動埠是 49152,而新的預設埠是 65535。 此增加與使用預設埠範圍 1025 到 5000 的舊版 Windows 組態不同。

您可以使用下列 netsh 命令來檢視電腦上的動態埠範圍:

  • netsh int ipv4 show dynamicport tcp
    
  • netsh int ipv4 show dynamicport udp
    
  • netsh int ipv6 show dynamicport tcp
    
  • netsh int ipv6 show dynamicport udp
    

此範圍會針對每個傳輸 (TCP 或 UDP) 個別設定。 埠範圍現在是具有起點和結束點的範圍。 如果在內部網路上使用防火牆,部署執行 Windows Server 之伺服器的 Microsoft 客戶可能會遇到會影響伺服器之間 RPC 通訊的問題。 在這些情況下,建議您重新設定防火牆,以允許 49152 到 65535 動態埠範圍內伺服器之間的流量。 此範圍是服務和應用程式所使用的已知埠之外。 或者,您可以在每部伺服器上修改伺服器所使用的埠範圍。 您可以使用 netsh 命令來調整此範圍,如下所示。 上述命令會設定 TCP 的動態埠範圍。

netsh int <ipv4|ipv6> set dynamic <tcp|udp> start=number num=range

起始埠是 number,而埠的總數是範圍。 以下是範例命令:

  • netsh int ipv4 set dynamicport tcp start=10000 num=1000
    
  • netsh int ipv4 set dynamicport udp start=10000 num=1000
    
  • netsh int ipv6 set dynamicport tcp start=10000 num=1000
    
  • netsh int ipv6 set dynamicport udp start=10000 num=1000
    

這些範例命令會將動態埠範圍設定為從埠 10000 開始,並在埠 10999 (1000 個埠) 結束。 可設定的埠最小範圍為 255。 可以設定的最小起始埠是 1025。 根據) 設定的範圍 (埠上限不能超過 65535。 若要複製 Windows Server 2003 的預設行為,請使用 1025 作為開始埠,然後使用 3976 作為 TCP 和 UDP 的範圍。 此使用模式會導致起始埠為 1025 且結束埠為 5000。

具體而言,關於連入連線的輸出連線不需要暫時埠來接受連線。

由於輸出連線開始失敗,您會看到下列行為的許多實例:

  • 無法使用網域認證登入計算機,但使用本機帳戶登入可以運作。 網域登入會要求您連絡DC進行驗證,這同樣是輸出連線。 如果您已設定快取認證,則網域登入可能仍可運作。

    事件檢視器 中 NETLOGON 錯誤的螢幕快照。

  • 群組原則 更新失敗:

    群組原則 失敗的事件屬性螢幕快照。

  • 無法存取檔案分享:

    錯誤訊息 Windows 無法存取的螢幕快照。

  • 來自受影響伺服器的 RDP 失敗:

    遠端桌面無法連線時發生錯誤的螢幕快照。

  • 在電腦上執行的任何其他應用程式都會開始提供錯誤

重新啟動伺服器將會暫時解決此問題,但您會看到所有徵兆在一段時間后恢復。

如果您懷疑電腦處於埠耗盡狀態:

  1. 嘗試建立輸出連線。 從伺服器/計算機存取遠端共用,或嘗試將 RDP 連線到另一部伺服器或埠上伺服器的 telnet。 如果所有這些選項的輸出連線失敗,請移至下一個步驟。

  2. 開啟事件查看器,然後在系統記錄檔下,尋找清楚指出目前狀態的事件:

    1. 事件標識碼 4227

      事件檢視器 中事件標識碼 4227 的螢幕快照。

    2. 事件標識碼 4231

      事件檢視器 中事件標識碼 4231 的螢幕快照。

  3. netstat -anob從伺服器收集輸出。 netstat 輸出會顯示單一 PID TIME_WAIT狀態的大量專案。

    netstate 命令輸出的螢幕快照。

    在工作階段正常關閉或突然關閉之後,在 4 分鐘 (預設) 之後,進程或應用程式所使用的埠會放回可用的集區。 在這 4 分鐘期間,TCP 連線狀態會TIME_WAIT狀態。 在您懷疑埠耗盡的情況下,應用程式或進程將無法釋放其已取用的所有埠,且會維持在TIME_WAIT狀態。

    您可能也會在相同的輸出中看到CLOSE_WAIT狀態連線;不過,當 TCP 對等的一端沒有其他數據可傳送 (FIN 傳送) ,但能夠從另一端接收數據時,CLOSE_WAIT狀態是一種狀態。 此狀態不一定表示埠耗盡。

    注意事項

    在TIME_WAIT狀態下擁有大型連線,不一定表示伺服器目前已超出埠,除非驗證前兩個點。 有許多TIME_WAIT連線確實表示程式正在建立大量的 TCP 連線,而且最終可能會導致埠耗盡。

    Netstat 已在 Windows 10 中更新,並新增 -Q 了 參數,以顯示已轉換過時間等候的埠,如同處於 BOUND 狀態一樣。 已發行 Windows 8.1 和 Windows Server 2012 R2 的更新,其中包含這項功能。 Windows 10 中的PowerShell Cmdlet Get-NetTCPConnection 也會顯示這些BOUND埠。

    在 2016/10 之前,netstat 不正確。 修正 netstat、back-ported 至 2012 R2、允許 Netstat.exe,以及Get-NetTcpConnection正確報告 Windows Server 2012 R2 中的 TCP 或 UDP 連接埠使用量。 若要深入瞭解,請參閱 Windows Server 2012 R2:暫時埠 Hotfix

  4. 在系統管理模式中開啟命令提示字元,然後執行下列命令。

    Netsh trace start scenario=netconnection capture=yes tracefile=c:\Server.etl
    
  5. 使用網路監視器開啟 server.etl 檔案,然後在篩選區段中套用篩選 Wscore_MicrosoftWindowsWinsockAFD.AFD_EVENT_BIND.Status.LENTStatus.Code == 0x209。 您應該會看到表示 STATUS_TOO_MANY_ADDRESSES的專案。 如果您找不到任何專案,則伺服器仍然不會超出埠。 如果您找到它們,則可以確認伺服器已耗盡埠。

針對埠耗盡進行疑難解答

關鍵在於識別使用所有埠的進程或應用程式。 以下是一些可用來隔離至單一進程的工具

方法 1

從查看 netstat 輸出開始。 如果您使用 Windows 10 或 Windows Server 2016,則可以執行 命令netstat -anobq,並檢查最大專案為 BOUND 的進程識別碼。 或者,您也可以執行下列 PowerShell 命令來識別程式:

Get-NetTCPConnection | Group-Object -Property State, OwningProcess | Select -Property Count, Name, @{Name="ProcessName";Expression={(Get-Process -PID ($_.Name.Split(',')[-1].Trim(' '))).Name}}, Group | Sort Count -Descending 

大部分的埠流失是因為發生錯誤時,使用者模式進程未正確關閉埠所造成。 在使用者模式層級,埠 (實際套接字) 是句柄。 TaskManagerProcessExplorer 都能夠顯示句柄計數,這可讓您識別哪個進程正在取用所有埠。

針對 Windows 7 和 Windows Server 2008 R2,您可以更新 PowerShell 版本以包含上述 Cmdlet。

方法 2

如果方法 1 無法協助您在 Windows 10 之前識別程式 (,並 Windows Server 2012 R2) ,請查看任務管理員:

  1. 在詳細數據/進程下新增名為 「handles」 的數據行。

  2. 排序數據行句柄,以識別具有最多句柄數目的進程。 通常,句柄大於 3000 的進程可能是原因,但系統、 lsass.exestore.exesqlsvr.exe等進程除外。

    Windows 任務管理器中 handles 資料行的螢幕快照。

  3. 如果這些進程以外的任何進程具有較高的數目,請停止該進程,然後嘗試使用網域認證登入,並查看它是否成功。

方法 3

如果任務管理員無法協助您識別程式,請使用 [進程總管] 來調查問題。

使用行程總管的步驟:

  1. 下載 [進程總管] ,並將其 提升許可權執行。

  2. Alt + 選取數據行標頭,選取 [選擇數據行],然後在 [ 處理效能] 索引標籤上,新增 [句柄計數]

  3. 取 [檢視>顯示下方窗格]

  4. 取 [檢視>下方窗格檢視>句柄]

  5. 選取要依該值排序 的 [處理] 資料行。

  6. 如果您無法建立輸出連線) ,檢查處理計數高於其餘 (可能會超過 10,000 個。

  7. 按兩下即可反白顯示其中一個句柄計數較高的進程。

  8. 在下方窗格中,如下所列的句柄為套接字。 (套接字是技術上的檔句柄) 。

    檔案 \Device\AFD

    [進程總管] 的螢幕快照,其中包含依句柄排序的進程。

  9. 有些是正常的,但其中有許多 (數百到數千個) 。 關閉有問題的程式。 如果還原輸出連線能力,則您已進一步證明應用程式是原因。 請連絡該應用程式的廠商。

最後,如果上述方法無法協助您隔離程式,建議您收集處於問題狀態之機器的完整記憶體轉儲。 傾印會告訴您哪個進程具有最大句柄。

因應措施是將計算機重新啟動,使其回到正常狀態,並協助您暫時解決問題。 不過,當重新啟動不切實際時,您也可以考慮使用下列命令增加計算機上的埠數目:

netsh int ipv4 set dynamicport tcp start=10000 num=1000

此命令會將動態埠範圍設定為從埠 10000 開始,並在埠 10999 (1000 個埠) 結束。 可設定的埠最小範圍為 255。 可以設定的最小起始埠是 1025。 根據) 設定的範圍 (埠上限不能超過 65535。

注意事項

請注意,增加動態埠範圍不是永久的解決方案,而只是暫時性的。 您必須追蹤哪些進程/處理器耗用最多埠數目,並從該程序的觀點進行疑難解答,以了解為何會耗用如此大量的埠。

針對 Windows 7 和 Windows Server 2008 R2,您可以使用下列腳本來以定義的頻率收集 netstat 輸出。 從輸出中,您可以看到埠使用趨勢。

@ECHO ON
set v=%1
:loop
set /a v+=1
ECHO %date% %time% >> netstat.txt
netstat -ano >> netstat.txt
 
PING 1.1.1.1 -n 1 -w 60000 >NUL
 
goto loop

其他相關資訊

  • 埠耗盡和您! - 本文提供 netstat 狀態的詳細數據,以及如何使用 netstat 輸出來判斷埠狀態
  • 偵測暫時埠耗盡:本文有一個腳本會在迴圈中執行,以報告埠狀態。 (適用於 Windows 2012 R2、Windows 8、Windows 10 和 Windows 11)