前言
准確的說,他是一個網絡連接端口查看器,可以根據進程查端口,也可以根據端口查進程。期初是因在使用Fiddler的時候發現無法啟動,提示端口被占用,但是由不知道用什么方法才能找到是哪個程序占用的Fiddler的端口,遂使用命令行的netstat命令配合find命令才找到,遂想寫這樣一個類似的工具幫助我們速度定位類似端口問題的所在。
PS:可預見很多人會說為什么不用360網絡鏈接查看器,或是其他類似軟件,功能更強大界面更美觀巴拉巴拉…?
答:因為我喜歡bat批處理,我喜歡命令行,喜歡能用幾句命令搞定的事就不用一個別的軟件來搞,更重要的是享受編寫代碼這其中的過程。
使用方法
主要功能就兩個:
1、查詢某個進程都在使用哪些端口號,包含同進程名的所有實例,以及他們分別所占用的TCP和UDP端口。
2、查看某個端口被哪個進程使用,包括遠程IP和本地IP,以及TCP和UDP的所有端口
如何看懂顯示列表
程序界面:
本程序返回值使用的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回車
可以看到紅框內,Fiddler占用了本地IPv4和IPv6的8888端口,並且一直處於監聽(LISTENING)狀態。
注意:最后一行的[::]表示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和127.0.0.1的區別可以參考:紅黑,文庫,stackoverflow,以及 知乎的討論等
好了扯遠了,繼續說bat用法,看到本地全零地址,以及監聽狀態,就可以判斷此程序Fiddler在占用8888端口,此時若有其他程序如IIS,湯姆貓之類的程序要啟動同端口就會報錯了。
再看看QQ的占用情況:
可以看到當前有兩個進程叫QQ.exe,他們的分別的鏈接情況及TCP、UDP鏈接如圖所示。
查詢某端口被哪個進程所占用
這里我們依舊測試Fiddler的8888端口,這里輸入2回車,輸入端口號8888回車,查看結果:
可以看到8888端口在IPv4和IPv6上都由Fiddler.exe在占用(監聽)
幫助信息:
注意:若無法使用或查詢無響應,請使用管理員權限啟用本批處理,方法可以參照我之前寫的文章:如何創建管理員權限的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