[批處理]NetstatFilter快速查找端口被佔用問題

前言

準確的說,他是一個網絡鏈接端口查看器,能夠根據進程查端口,也能夠根據端口查進程。期初是因在使用Fiddler的時候發現沒法啓動,提示端口被佔用,可是由不知道用什麼方法才能找到是哪一個程序佔用的Fiddler的端口,遂使用命令行的netstat命令配合find命令才找到,遂想寫這樣一個相似的工具幫助咱們速度定位相似端口問題的所在。html

 

PS:可預見不少人會說爲何不用360網絡連接查看器,或是其餘相似軟件,功能更強大界面更美觀巴拉巴拉…?git

答:由於我喜歡bat批處理,我喜歡命令行,喜歡能用幾句命令搞定的事就不用一個別的軟件來搞,更重要的是享受編寫代碼這其中的過程。github

使用方法

 

image

主要功能就兩個:編程

一、查詢某個進程都在使用哪些端口號,包含同進程名的全部實例,以及他們分別所佔用的TCP和UDP端口。windows

二、查看某個端口被哪一個進程使用,包括遠程IP和本地IP,以及TCP和UDP的全部端口服務器

 

如何看懂顯示列表

程序界面:網絡

image

 

本程序返回值使用的windows命令行下的netstat命令。函數

什麼是netstat命令?

Netstat,在Internet RFC標準中,Netstat的定義是: Netstat是在內核中訪問網絡及相關信息的程序,它能提供TCP鏈接,TCP和UDP監聽,進程內存管理的相關報告。工具

具體的關於netstat命令的用法能夠參見:netstat百度百科WIKI如何用netstat命令查看端口占用問題測試

什麼是PID?

PID(ProcessID)操做系統裏指進程ID號。操做系統裏每打開一個程序都會建立一個進程ID,即PID。
PID就是各進程的身份標識,程序一運行系統就會自動分配給進程一個獨一無二的PID。進程停止後PID被系統回收,可能會被繼續分配給新運行的程序。
PID一列表明瞭各進程的進程ID,也就是說,PID就是各進程的身份標識。

「狀態」字段有哪些類型及含義?

鏈接狀態。在原模式中沒有狀態,在用戶數據報協議中也常常沒有狀態,因而狀態列能夠空出來。如有狀態,一般取值爲:
LISTEN
偵聽來自遠方的TCP端口的鏈接請求
SYN-SENT
在發送鏈接請求後等待匹配的鏈接請求
SYN-RECEIVED
在收到和發送一個鏈接請求後等待對方對鏈接請求的確
ESTABLISHED
表明一個打開的鏈接
FIN-WAIT-1
等待遠程TCP鏈接中斷請求,或先前的鏈接中斷請求的確認
FIN-WAIT-2
從遠程TCP等待鏈接中斷請求
CLOSE-WAIT
等待從本地用戶發來的鏈接中斷請求
CLOSING
等待遠程TCP對鏈接中斷的確認
LAST-ACK
等待原來的發向遠程TCP的鏈接中斷請求的確認
TIME-WAIT
等待足夠的時間以確保遠程TCP接收到鏈接中斷請求的確認

CLOSED
沒有任何鏈接狀態

什麼是本地地址,外部地址?

簡單的講,本地地址即當前這個連接到你本機通訊的IP地址和端口,外部地址即當前這個連接到的遠程服務器地址和端口。

固然本地和外部地址都有多是本地地址,通常端口不同而已。一個典型的應用就是代理服務軟件

具體的能夠參見:端口百科 中相關地址的解釋,或是參見:NAT概念中的四類地址概念,也有助於理解。

查詢某進程佔用的端口號

這裏咱們查詢Fiddler.exe所佔用的端口號,在主界面選擇1,回車。再輸入Fiddler回車

image

 

能夠看到紅框內,Fiddler佔用了本地IPv4和IPv6的8888端口,而且一直處於監聽(LISTENING)狀態。

image

注意:最後一行的[::]表示IPv6的全部地址,等同於IPv4的0.0.0.0地址

此地址在不一樣環境有不一樣名稱,若在路由表中他表示默認路由。在網絡編程中,若監聽此地址的端口,則可至關於同時監聽本地迴環地址127.0.0.1以及localhost地址以及本機全部網卡的本地地址(如192.168.1.100)的端口。

反之,若只監聽當前網卡本地地址192.168.1.100的端口,則使用127.0.0.1地址就訪問不到

關於什麼是0.0.0.0地址能夠參考:WIKI這裏

關於0.0.0.0和127.0.0.1的區別能夠參考:紅黑文庫stackoverflow,以及 知乎的討論

 

好了扯遠了,繼續說bat用法,看到本地全零地址,以及監聽狀態,就能夠判斷此程序Fiddler在佔用8888端口,此時如有其餘程序如IIS,湯姆貓之類的程序要啓動同端口就會報錯了。

 

再看看QQ的佔用狀況:

image

能夠看到當前有兩個進程叫QQ.exe,他們的分別的連接狀況及TCP、UDP連接如圖所示。

查詢某端口被哪一個進程所佔用

這裏咱們依舊測試Fiddler的8888端口,這裏輸入2回車,輸入端口號8888回車,查看結果:

image

能夠看到8888端口在IPv4和IPv6上都由Fiddler.exe在佔用(監聽)

 

幫助信息:

image

 

注意:若沒法使用或查詢無響應,請使用管理員權限啓用本批處理,方法能夠參照我以前寫的文章:如何建立管理員權限的CMD命令提示符窗口

 

程序源碼下載

源碼已經託管至Github:

https://github.com/xxcanghai/cnblogsFiles/blob/master/NetstatFilter網絡鏈接查看器.bat

 

或是直接複製下述全部代碼保存到.bat文件後,直接運行便可。

批處理代碼:

::NetstatFilter網絡鏈接查看器 @小小滄海 xxcanghai.cnblogs.com By:2015年6月29日
@echo off
:start
title NetstatFilter By:xxcanghai
SETLOCAL ENABLEEXTENSIONS&SETLOCAL ENABLEDELAYEDEXPANSION
cls

::######config######
set PCENAME=
set PID=
set PORT=

::inner config
set ERRORCODE=0

:menu
cls&echo ----------NetstatFilter----------
echo [1]查詢指定進程名使用的端口號
echo [2]查看指定端口被哪一個進程使用
echo [3]幫助信息
echo.
set /p=請輸入對應數字:<nul
set select=3&set /p select=
if /i "%select%"=="q" exit /b
if /i "%select%"=="exit" exit /b
if "%select%"=="1" goto :menuitem1
if "%select%"=="2" goto :menuitem2
if "%select%"=="3" goto :help
cls&goto :menu

:menuitem1
set /p=請輸入要查詢的進程名稱:<nul
set PCENAME=&set /p PCENAME=
if /i "%PCENAME%"=="q" goto :menu
if "%PCENAME%"=="" goto :menuitem1
if "%PCENAME:.=%"=="%PCENAME%" set PCENAME=%PCENAME%.exe
call :getpid "%PCENAME%" PID
echo Process:%PCENAME%,PID:%PID%
call :getnetbypid "%PID%"
echo @1END&pause>nul&goto start


:menuitem2
set /p=請輸入要查詢的端口號:<nul
set PORT=&set/p PORT=
if /i "%PORT%"=="q" goto :menu
if "%PORT%"=="" goto :menuitem2
call :getnetbyport "%PORT%"
echo @2END&pause>nul&goto start


:help
cls
echo ┏━━━━━━━━━━━━━━NetstatFilter ━━━━━━━━━━━━━━━━┓
echo ┃           netstat命令的輔助工具 @小小滄海 xxcanghai.cnblogs.com          ┃
echo ┃                                                                          ┃
echo ┃1.可查詢某個進程在使用哪些端口,包含同名進程的多個實例及全部TCP和UDP端口  ┃
echo ┃2.可查詢指定端口正在被哪些進程使用,以及本地/遠程IP端口和當前鏈接狀態     ┃
echo ┃                                =注意=echo ┃※1.若沒法使用或查詢無反應請用管理員權限執行本批處理,方法參照上述博客文章┃
echo ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

echo 按任意鍵返回主菜單&pause>nul&goto start

::#####get pid by process#####
::[tasklist] example
::cmd.exe                      11132 Console                    1      3,000 K
::cmd.exe                       8204 Console                    1      2,728 K
::cmd.exe                      10060 Console                    1      2,996 K
:getpid
if not "%~1"=="" (
    set PID=
    for /f "tokens=2 delims= " %%i in ('tasklist /fi "imagename eq %~1" /nh /fo table^|find /i "%~1"') do (
        set PID=!PID!%%i,
    )
    if "!PID!"=="" (
        set ERRORCODE=101
        echo [ERROR]ProcessName "%~1" is not found
        pause>nul&goto start
    ) else (
        set PID=!PID:~0,-1!
    )
    set %2=!PID!
    goto :eof
)


::#####get netstat by pid#####
::[netstat] example:
::  Proto  Local Address          Foreign Address        State           PID
::   TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4
::   UDP    [::1]:50575            *:*                                    5108
:getnetbypid
if not "%~1"=="" (
    set PID=%~1
    for /f "tokens=1,* delims=," %%a in ("!PID!") do (
        set subpid=%%a
        set PID=%%b
        ::get TCP
        echo [PID-!subpid!]:
        for /f "delims=" %%z in ('netstat -a -n -o^|find ":"') do (
            set tLine=%%z
            ::netstat的IPv6結果中含有%符號,%符號在call傳遞中會發生錯誤,遂將%替換爲$後再傳遞
            set tLine=!tLine:%%=$!
            call :getNetInfo "!tLine!" tProto tLocalAdd tForeignAdd tState tPID
            set tLine=!tLine:$=%%!
            ::call使用完成後將$符號替換回%符號
            if "!tPID!"=="!subpid!" (
                echo !tLine!
            )
        )
    )
    if not "!PID!"=="" (call %0 "!PID!")
    goto :eof
)


::#####get netstat by port#####
:getnetbyport
if not "%~1"=="" (
    set PORT=%~1
    for /f "tokens=1,* delims=," %%a in ("!PORT!") do (
        set myport=%%a
        set PORT=%%b
        ::PORT==8888
        for /f "delims=" %%z in ('netstat -a -n -o^|find /i ":!myport! "') do (
            set tLine=%%z            
            set tLine=!tLine:%%=$!
            call :getNetInfo "!tLine!" tProto tLocalAdd tForeignAdd tState tPID
            set tLine=!tLine:$=%%!            
            echo !tLine!
            for /f "tokens=1 delims= " %%j in ('tasklist /nh /fi "PID eq !tPID!"') do (
                echo [%%j]
            )
        )
    )
)
goto :eof


echo END.&pause>nul&goto start
exit

::#####FUNCTION#####
:getNetInfo
::將netstat -ano的某一行分隔成不一樣的變量
::call :getNetInfo "<netstat output line>" tProto tLocalAdd tForeignAdd tState tPID
if not "%~1"=="" (
    for /f "tokens=1,2,3,4,5 delims= " %%i in ("%~1") do (
        set %2=%%i
        set %3=%%j
        set %4=%%k
        if "%%i"=="TCP" (
            set %5=%%l
            set %6=%%m
        ) else (
            set %5=
            set %6=%%l
        )
    )
)
goto :eof

::#####FUNCTION#####
:split
::%0爲函數名稱自身:split,%1爲傳過來的值,%~1爲刪除變量中的雙引號"
::在此子搜索函數中把過濾器按照/符號分割開,並取得分割後的第一個的值
::再把分割後的剩下的值重賦予過濾器,並調用自身,直到過濾器爲空爲止,返回
set subf=%~1
for /f "tokens=1,* delims=," %%j in ("%subf%") do (

    set subf=%%k
)
if not "!subf!"=="" (call %0 "!subf!")
goto :eof


::#####FUNCTION#####
:FUN1

goto :eof
原文地址-小小滄海:http://www.cnblogs.com/xxcanghai/p/4958577.html
相關文章
相關標籤/搜索