Golang 协程TCP扫描退出问题

问题描述

我想要通过协程扫描目标主机范围内的开放端口,比如扫描baidu.com的1-1024端口。

但是我写的代码会提前退出,还没有将net.Dial的结果插入retChan管道就已经退出主协程了。

问题出现的环境背景及自己尝试过哪些方法

在看了很多协程池之类的方法后还是失败...

相关代码

package main

import (
    "fmt"
    "net"
    "time"
)

func scanPort(jobChan <-chan int, retChan chan<- string) {
    // 从管道取端口
    for port := range jobChan {

        // 发起tcp连接
        target := fmt.Sprintf("149.129.68.235:%d", port)

        _, err := net.Dial("tcp", target)

        // 未发生错误时写入结果管道
        if err == nil {
            retChan <- fmt.Sprintf("%s is open", target)
        }

    }
}

func main() {
    jobChan := make(chan int, 65535)
    retChan := make(chan string, 65535)

    // 写入1024个待扫描端口到任务管道
    go func() {
        for i := 0; i < 1024; i++ {
            jobChan <- i
        }
    }()

    // 创建n个协程
    for i := 0; i < 10; i++ {
        go scanPort(jobChan, retChan)
    }

    // 关闭
    time.Sleep(time.Second)
    close(retChan)

    // 打印结果
    for ret := range retChan {
        fmt.Println(ret)
    }

}

你期待的结果是什么?实际看到的错误信息又是什么?

能够正常扫描到已开放的端口

阅读 1.9k
1 个回答

你的代码如何保证 close时, 你的协程已经处理完所有的逻辑呢,你主进程休眠的1秒,未必够啊
正确的做法,使用 sync.WaitGroup

同时,通道容量不用设置那么大,处理好写入和读出的逻辑,很小的容量也可以运行下去,不堵塞就好

package main

import (
    "fmt"
    "net"
    "sync"
    "time"
)

func scanPort(jobChan <-chan int, retChan chan<- string, wg *sync.WaitGroup) {
    defer wg.Done()
    // 从管道取端口
    for port := range jobChan {
        // 发起tcp连接
        target := fmt.Sprintf("149.129.68.235:%d", port)
        //fmt.Println(target)
        _, err := net.DialTimeout("tcp", target, 100*time.Millisecond)
        //_, err := net.Dial("tcp", target)
        // 未发生错误时写入结果管道
        if err == nil {
            retChan <- fmt.Sprintf("%s is open", target)
        }

    }
}

func main() {
    jobChan := make(chan int, 5)
    retChan := make(chan string, 5)

    // 写入1024个待扫描端口到任务管道
    go func() {
        for i := 0; i < 1024; i++ {
            jobChan <- i
        }
        close(jobChan)
    }()
    wg := sync.WaitGroup{}
    // 创建n个协程
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go scanPort(jobChan, retChan, &wg)
    }
    go func() {
        for ret := range retChan {
            fmt.Println(ret)
        }
    }()
    // 关闭
    wg.Wait()
    close(retChan)
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题