我目前正在学习围棋。为此,我制作了一个相对简单的portscanner。
我面临的问题是,扫描这些端口需要相当长的时间。我的行为是,如果我扫描端口(定义为一组int32 (协议不支持int16) ),不使用goroutines工作,但当扫描超过5个端口时,你可以想象到相当慢,因为它不是并行运行的。
为了实现并行性,我想出了以下代码(解释+问题在代码之后):
//entry point for port scanning
var results []*portscan.ScanResult
//len(splitPorts) is the given string (see benchmark below) chopped up in an int32 slice
ch := make(chan *portscan.ScanResult, len(splitPorts))
var wg sync.WaitGroup
for _, port := range splitPorts {
connect(ip, port, req.Timeout, ch, &wg)
}
wg.Wait()
for elem := range ch {
results = append(results, elem)
}
// go routine
func connect(ip string, port, timeout int32, ch chan *portscan.ScanResult, wg *sync.WaitGroup) {
wg.Add(1)
go func() {
res := &portscan.ScanResult{
Port: port,
IsOpen: false,
}
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), time.Duration(timeout)*time.Millisecond)
if err == nil {
conn.Close()
res.IsOpen = true
}
ch <- res
wg.Done()
}()
}因此,protobuf为我准备了一个结构,如下所示:
type ScanResult struct {
Port int32 `protobuf:"varint,1,opt,name=port" json:"port,omitempty"`
IsOpen bool `protobuf:"varint,2,opt,name=isOpen" json:"isOpen,omitempty"`
}如代码片段的第一行所示,我定义了一个切片来保存所有结果,其思想是我的应用程序并行扫描端口,完成后,将结果发送给感兴趣的任何人。
但是,使用此代码时,程序会卡住。
我运行这个基准来测试它的性能:
func BenchmarkPortScan(b *testing.B) {
request := &portscan.ScanPortsRequest{
Ip: "62.129.139.214",
PortRange: "20,21,22,23",
Timeout: 500,
}
svc := newService()
for i := 0; i < b.N; i++ {
svc.ScanPorts(nil, request)
}
}它被卡住的原因是什么?看看这段代码会泄露什么吗?
因此,简而言之,我希望我的最终结果是每个端口都在不同的go例程中进行扫描,当它们都完成时,所有内容都在ScanResult的结果切片中聚集在一起。
我希望我已经讲清楚了,并为你们提供了足够的信息来帮助我。
哦,我特别寻找的是指针和学习部分,而不是查看工作代码示例。
https://stackoverflow.com/questions/38422600
复制相似问题