logo头像

技术引领生活!

go语言协程池之端口扫描器

学习下GO语言的协程的端口扫描,更多教程见大神的bilibili主页

视频链接

参见微软MVP杨旭大神的Go语言(Golang)编写 TCP 端口扫描器(完结)

步骤

  1. 开启协程池
  2. 投递任务(用go routine实现)
  3. 获取结果(注意这里的数量要和分配的任务相同)
  4. 收尾(关闭chan)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package main

import (
"flag"
"fmt"
"net"
"sort"
"strconv"
"time"
)

func worker(ip string, ports chan int, result chan int) {
for port := range ports {
addr := net.JoinHostPort(ip, strconv.Itoa(port))

conn, err := net.Dial("tcp", addr)
if err != nil {
result <- 0
continue
}

conn.Close()
result <- port
}
}

func main() {
//0. 初始化变量,读取ip
var ip string
flag.StringVar(&ip, "ip", "127.0.0.1", "input ip for scan(support ipv4/6)")
flag.Parse()
fmt.Printf("scan (%s) range 1~65535\n", ip)

// 使用带缓冲的chan来存储任务,非缓冲的chan获取结果
jobs := make(chan int, 10240)
result := make(chan int)

start := time.Now()

var openedPorts []int
//1.开启协程池
for p := 0; p < cap(jobs); p++ {
go worker(ip, jobs, result)
}

//2. 投递任务
go func() {
for j := 1; j <= 65535; j++ {
jobs <- j
}
}()

//3. 获取结果(注意这里的数量要和分配的任务相同)
for j := 1; j <= 65535; j++ {
r := <-result

if r != 0 {
openedPorts = append(openedPorts, r)
}
}

//4. 关闭chan,否则 worker里面会一直循环
close(jobs)
close(result)

//排序
fmt.Println("open ports:")
sort.Ints(openedPorts)
for _, port := range openedPorts {
fmt.Println(port)
}

since := time.Since(start)
fmt.Printf("time consuming %v", since)

}


支付宝打赏 微信打赏

您的支持是我前行的动力!