我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么用Go语言打造一款简易TCP端口扫描器

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么用Go语言打造一款简易TCP端口扫描器

这篇文章主要介绍“怎么用Go语言打造一款简易TCP端口扫描器”,在日常操作中,相信很多人在怎么用Go语言打造一款简易TCP端口扫描器问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用Go语言打造一款简易TCP端口扫描器”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

TCP扫描本质

我们在使用TCP进行连接时,需要知道对方机器的ip:port

正常握手

连接成功的话,流程如下。

怎么用Go语言打造一款简易TCP端口扫描器

连接失败

有正常,就有失败,如果被连接方关闭的话,流程如下。

怎么用Go语言打造一款简易TCP端口扫描器

如果有防火墙

还有一种可能是,端口开放,但是防火墙拦截,流程如下。

怎么用Go语言打造一款简易TCP端口扫描器

代码

本质理解之后,就可以开始撸代码了。

在Go中,我们通常使用net.Dial进行TCP连接

它就两种情况

  • 成功:返回conn。

  • 失败:err != nil。

普通版

相对来说,刚开始时,我们可能都不是太胆大,都是先写原型,也不考虑性能。

代码

package main  import (     "fmt"     "net" )  func main() {     var ip = "192.168.43.34"     for i := 21; i <= 120; i++ {         var address = fmt.Sprintf("%s:%d", ip, i)         conn, err := net.Dial("tcp", address)         if err != nil {             fmt.Println(address, "是关闭的")             continue         }         conn.Close()         fmt.Println(address, "打开")   } }

执行结果

怎么用Go语言打造一款简易TCP端口扫描器

但是这个过程是非常缓慢的。

因为net.Dial如果连接的是未开放的端口,一个端口可能就是20s+,所以,我们为什么学习多线程懂了把!!!

多线程版

上述是通过循环去一个个连接ip:port的,那我们就知道了,在一个个连接的位置,让多个人去干就好了。

所以,多线程如下。

代码

package main  import (     "fmt"     "net"     "sync"     "time" )  func main() {      var begin =time.Now()     //wg     var wg sync.WaitGroup     //ip     var ip = "192.168.99.112"     //var ip = "192.168.43.34"     //循环     for j := 21; j <= 65535; j++ {         //添加wg         wg.Add(1)         go func(i int) {             //释放wg             defer wg.Done()             var address = fmt.Sprintf("%s:%d", ip, i)             //conn, err := net.DialTimeout("tcp", address, time.Second*10)             conn, err := net.Dial("tcp", address)             if err != nil {                 //fmt.Println(address, "是关闭的", err)                 return             }             conn.Close()             fmt.Println(address, "打开")         }(j) }     //等待wg     wg.Wait()     var elapseTime = time.Now().Sub(begin)     fmt.Println("耗时:", elapseTime) }

执行结果

 怎么用Go语言打造一款简易TCP端口扫描器

其实是同时开启了6W多个线程,去扫描每个ip:port。

所以耗时最长的线程结束的时间,就是程序结束的时间。

感觉还行,20s+扫描完6w多个端口!!!

线程池版

上面我们简单粗暴的方式为每个ip:port都创建了一个协程。

虽然在Go中,理论上协程开个几十万个都没问题,但是还是有一些压力的。

所以我们应该采用一种相对节约的方式进行精简代码,一般采用线程池方式。

本次使用的线程池包:gohive

地址:https://github.com/loveleshsharma/gohive

简单介绍

怎么用Go语言打造一款简易TCP端口扫描器

代码

package main  //线程池方式 import (     "fmt"     "github.com/loveleshsharma/gohive"     "net"     "sync"     "time" )  //wg var wg sync.WaitGroup  //地址管道,100容量 var addressChan = make(chan string, 100)  //工人 func worker() {     //函数结束释放连接     defer wg.Done()     for {         address, ok := <-addressChan         if !ok {             break         }         //fmt.Println("address:", address)         conn, err := net.Dial("tcp", address)         //conn, err := net.DialTimeout("tcp", address, 10)         if err != nil {             //fmt.Println("close:", address, err)             continue         }         conn.Close()         fmt.Println("open:", address) } } func main() {     var begin = time.Now()     //ip     var ip = "192.168.99.112"     //线程池大小     var pool_size = 70000     var pool = gohive.NewFixedSizePool(pool_size)      //拼接ip:端口     //启动一个线程,用于生成ip:port,并且存放到地址管道种     go func() {         for port := 1; port <= 65535; port++ {             var address = fmt.Sprintf("%s:%d", ip, port)             //将address添加到地址管道             //fmt.Println("<-:",address)             addressChan <- address         }         //发送完关闭 addressChan 管道         close(addressChan) }()     //启动pool_size工人,处理addressChan种的每个地址     for work := 0; work < pool_size; work++ {         wg.Add(1)         pool.Submit(worker) }     //等待结束     wg.Wait()     //计算时间     var elapseTime = time.Now().Sub(begin)     fmt.Println("耗时:", elapseTime) }

执行结果

怎么用Go语言打造一款简易TCP端口扫描器

我设置的线程池大小是7w个,所以也是一下子开启6w多个协程的,但是我们已经可以进行线程大小约束了。

假设现在有这样的去求,有100个ip,需要扫描每个ip开放的端口,如果采用简单粗暴开线程的方式.

那就是100+65535=6552300,600多w个线程,还是比较消耗内存的,可能系统就会崩溃,如果采用线程池方式。

将线程池控制在50w个,或许情况就会好很多。

但是有一点的是,在Go中,线程池通常需要配合chan使用,可能需要不错的基础。

到此,关于“怎么用Go语言打造一款简易TCP端口扫描器”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么用Go语言打造一款简易TCP端口扫描器

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

目录