编辑代码

package main

import (
    "errors"
    "fmt"
    "math/rand"
    "net"
    "sync"
    "time"
    "unsafe"
)

const (
    // concurrency = 100
    concurrency = 2
)
var (
    ip = "127.0.0.1"
    // portStart, portEnd = 1, 65535
    portStart, portEnd = 1, 15

    openPorts []int
)

func main () {
    startAt := time.Now()
    defer func(ts time.Time) {
        spend := time.Since(ts)
        fmt.Printf("<<< IP scan [end] (spend time: %v seconds.)\n", spend)
    }(startAt)

    fmt.Printf(">>> IP scan [start]...\n")

    scanIpAddress(ip, portStart, portEnd)

    fmt.Printf("Open ports total: %d \n", len(openPorts))
    if len(openPorts) > 0 {
        fmt.Printf("Open ports: %v \n", openPorts)
    }
}

func scanIpAddress(ip string, portStart, portEnd int) {
    // verify params
    if ok, err := verifyParams(ip, portStart, portEnd); ok == false {
        fmt.Printf("----- verify-params error: %s \n", err.Error())
        return
    }

    portCh := make(chan int, concurrency)
    defer close(portCh)
    
    var wg sync.WaitGroup

    for i := 0; i < cap(portCh); i++ {
        go handleWorker(ip, portCh, &wg)
    }

    for j := portStart; j <= portEnd; j++ {
        wg.Add(1)
        portCh <- j

        // time.Sleep(time.Second * time.Duration(1))
    }
    wg.Wait()
}

func handleWorker(ip string, ports chan int, wg *sync.WaitGroup) {

    rand.Seed(time.Now().UnixNano())
    qNo := fmt.Sprintf("q_%d", rand.Intn(999))
    fmt.Printf("----- [Run & Wait] handleWorker() [%s] ----- \n", qNo)
    
    for port := range ports {
        addr := fmt.Sprintf("%s:%d", ip, port)
        if conn, err := net.Dial("tcp", addr); err == nil {
            openPorts = append(openPorts, port)
            conn.Close()
        }
        // else {
        //     // Closed
        // }
        wg.Done()
    }
}

func verifyParams(ip string, portStart, portEnd int) (ok bool, err error) {
    _ip := net.ParseIP(ip)
    if _ip == nil {
        err = errors.New("[ERROR] ip type is must net.ip")
        return
    }
    fmt.Printf("[INFO] ip=%s | ip type is: %T | ip size is: %d \n", _ip, _ip, unsafe.Sizeof(_ip))

    if portStart < 1 || portEnd > 65535 {
        err = errors.New("[ERROR] port is must in the range of 1~65535")
        return
    }
    fmt.Printf("[INFO] scan ports: %d~%d \n", portStart, portEnd)

    ok = true
    return
}