本文是根据源代码改编的,原代码路径

优化后的代码 port_scanner.go

package main

import (
    "fmt"
    "net"
    "os"
    "runtime"
    "strconv"
    "sync"
    "time"
)

func loop(inport chan int, startport, endport int) {
    for i := startport; i <= endport; i++ {
        inport <- i
    }
    close(inport)
}

type ScanSafeCount struct {
    count int
    mux   sync.Mutex
}

var scanCount ScanSafeCount

func scanner(inport int, outport chan int, ip string, endport int) {
    in := inport
    fmt.Printf(" %d ", in)
    host := fmt.Sprintf("%s:%d", ip, in)
    tcpAddr, err := net.ResolveTCPAddr("tcp4", host)
    if err != nil {
        // fmt.Printf("不行 %s\n", host)
        outport <- 0
    } else {
        conn, err := net.DialTimeout("tcp", tcpAddr.String(), 200*time.Millisecond)
        // conn, err := net.Dial("tcp", host)
        if err != nil {
            // fmt.Printf("不可以 %d\n", in)
            outport <- 0
        } else {
            outport <- in
            fmt.Printf("\n *************( %d 可以 )*****************\n", in)
            conn.Close()
        }

    }

    scanCount.mux.Lock()
    scanCount.count = scanCount.count - 1
    if scanCount.count <= 0 {
        close(outport)
    }
    scanCount.mux.Unlock()

}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    inport := make(chan int)
    outport := make(chan int)
    collect := []int{}

    fmt.Println(os.Args, len(os.Args))
    if len(os.Args) != 4 {
        fmt.Println("使用方式: port_scanner IP startport endport")
        os.Exit(0)
    }

    fmt.Println("扫描开始:", time.Now().Unix())

    ip := string(os.Args[1])
    startport, _ := strconv.Atoi(os.Args[2])
    endport, _ := strconv.Atoi(os.Args[3])

    if startport > endport {
        fmt.Println("Usage: scanner IP startport endport")
        fmt.Println("Endport must be larger than startport")
        os.Exit(0)
    } else {
        scanCount = ScanSafeCount{count: (endport - startport + 1)}
    }

    fmt.Printf("扫描 %s:%d----------%d\n", ip, startport, endport)

    go loop(inport, startport, endport)

    for v := range inport {
        go scanner(v, outport, ip, endport)
    }

    for port := range outport {
        if port != 0 {
            collect = append(collect, port)
        }
    }

    fmt.Println("--")
    fmt.Println(collect)
    fmt.Println("扫描结束", time.Now().Unix())

}

输入命令(192.168.0.110 是我的局域网 ip 地址, 开始端口和结束端口写的接近以便示例):

go run port_scanner.go 192.168.0.110 0000 0139

输出:

扫描开始: 1469689864
扫描 192.168.0.110:0----------139
 1  3  13  12  53  5  85  127  7  6  9  11  10  0  15  14  17  16  19  18  21  20  23  22  25  24  2
7  26  29  28  31  30  33  32  35  34  37  36  39  38  41  40  43  42  45  44  47  46  49  48  2  50
  51  52  55  54  57  56  59  58  61  60  63  62  65  64  67  66  69  68  71  70  73  72  75  74  77
  76  79  78  81  80  83  82  84  87  86  89  88  91  90  93  92  95  94  97  96  99  98  101  100
103  102  105  104  107  106  109  108  111  110  113  112  115  114  117  116  119  118  121  120
123  4  122  124  125  126  129  128  131  130  133  132  135  134
 *************( 135 可以 )*****************
 136  139
 *************( 139 可以 )*****************
 8  137  138 --
[135 139]
扫描结束 1469689864