go 實(shí)現(xiàn)簡(jiǎn)易端口掃描的示例
我在代碼里定義了兩個(gè)通道,分別用于生產(chǎn)端口和限制連接數(shù),如果不限制連接數(shù),容易被對(duì)方檢測(cè)到或?qū)е聦?duì)方服務(wù)器不能正常運(yùn)行。
// 生產(chǎn)端口 var port = make(chan int, 10) // 限制并發(fā)數(shù) var connect = make(chan string, 5)
可以使用net庫的Dial函數(shù)做為socket客戶端,需要注意的是要設(shè)置超時(shí)時(shí)間,因?yàn)槿糁鳈C(jī)不存在,或目標(biāo)端口是關(guān)閉的,往往需要花費(fèi)數(shù)秒才返回錯(cuò)誤,這樣掃描大量端口時(shí)效率會(huì)極其低下。在go中可以使用net.Dialer結(jié)構(gòu)體設(shè)置超時(shí)時(shí)間,然后在調(diào)用Dial方法:
d := net.Dialer{Timeout: time.Second} dial, err := d.Dial("tcp", target)
只要err不等于nil,表示目標(biāo)端口是對(duì)外開放的。
完整代碼如下:
package main import ( "fmt" "net" "sync" "time" ) var wg sync.WaitGroup func main() { var start, end int var address string fmt.Printf("請(qǐng)輸入目標(biāo)IP:> ") fmt.Scan(&address) fmt.Printf("請(qǐng)輸入起始端口:> ") fmt.Scan(&start) fmt.Printf("請(qǐng)輸入結(jié)束端口:> ") fmt.Scan(&end) wg.Add(end - start + 1) Run(address, start, end) wg.Wait() fmt.Println("執(zhí)行完畢") } // 生產(chǎn)端口 var port = make(chan int, 10) // 限制并發(fā)數(shù) var connect = make(chan string, 5) func Run(address string, start, end int) { go func() { for i := start; i <= end; i++ { port <- i } }() go func() { // 消費(fèi)端口 for p := range port { // 往通道寫入目標(biāo)地址,超過限制并發(fā)數(shù)會(huì)阻塞 connect <- fmt.Sprintf("%s:%d", address, p) } }() go Connect() } func Connect() { // 并發(fā)請(qǐng)求 for target := range connect { // 設(shè)置超時(shí)時(shí)間 d := net.Dialer{Timeout: time.Second} dial, err := d.Dial("tcp", target) if err == nil { fmt.Printf("%s 連接成功\n", target) dial.Close() }else{ fmt.Printf("%s 連接失敗\n", target) } wg.Done() } }
這里端口生產(chǎn)通道不是必須的,只是為了演示消費(fèi)生產(chǎn)并發(fā)模型,當(dāng)然這還是最簡(jiǎn)單的。
在Run函數(shù)里我沒有關(guān)閉這兩個(gè)通道,按官方的說法是gc會(huì)回收不使用的通道,如果要手動(dòng)關(guān)閉,可以定義defer閉包進(jìn)行close。
我本地運(yùn)行結(jié)果如下:
請(qǐng)輸入目標(biāo)IP:> 127.0.0.1 請(qǐng)輸入起始端口:> 8080 請(qǐng)輸入結(jié)束端口:> 8094 127.0.0.1:8080 連接成功 127.0.0.1:8081 連接成功 127.0.0.1:8082 連接成功 127.0.0.1:8083 連接成功 127.0.0.1:8084 連接成功 127.0.0.1:8085 連接成功 127.0.0.1:8086 連接成功 127.0.0.1:8087 連接成功 127.0.0.1:8088 連接成功 127.0.0.1:8089 連接成功 127.0.0.1:8090 連接成功 127.0.0.1:8091 連接成功 127.0.0.1:8092 連接成功 127.0.0.1:8093 連接失敗 127.0.0.1:8094 連接失敗 執(zhí)行完畢
這個(gè)版本比較簡(jiǎn)陋,TCP連接過程也可以簡(jiǎn)化,后續(xù)再寫另外一篇文章。因?yàn)樽罱趯W(xué)rust語言,語法內(nèi)容比較多,所以后面暫時(shí)發(fā)布編程相關(guān)的文章,提升一下語法熟練度。
以上就是go 實(shí)現(xiàn)簡(jiǎn)易端口掃描的示例的詳細(xì)內(nèi)容,更多關(guān)于go 實(shí)現(xiàn)端口掃描的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Go語言實(shí)現(xiàn)微信公眾平臺(tái)
這篇文章主要介紹了使用Go語言實(shí)現(xiàn)微信公眾平臺(tái),雖然不是全部代碼,但是也是給我們提供了一個(gè)非常好的思路,需要的朋友可以參考下2015-01-01自己動(dòng)手用Golang實(shí)現(xiàn)約瑟夫環(huán)算法的示例
這篇文章主要介紹了自己動(dòng)手用Golang實(shí)現(xiàn)約瑟夫環(huán)算法的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Go語言使用Redis和Etcd實(shí)現(xiàn)高性能分布式鎖
這篇文章主要為大家介紹了Go語言使用Redis實(shí)現(xiàn)高性能分布式鎖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12使用gin框架搭建簡(jiǎn)易服務(wù)的實(shí)現(xiàn)方法
go語言web框架挺多的,本文就介紹了一下如何使用gin框架搭建簡(jiǎn)易服務(wù)的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12golang實(shí)現(xiàn)mysql數(shù)據(jù)庫事務(wù)的提交與回滾
這篇文章主要介紹了golang實(shí)現(xiàn)mysql數(shù)據(jù)庫事務(wù)的提交與回滾,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04Golang 處理浮點(diǎn)數(shù)遇到的精度問題(使用decimal)
本文主要介紹了Golang 處理浮點(diǎn)數(shù)遇到的精度問題,不使用decimal會(huì)出大問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02