实现Ping和TCP端口扫描功能

This commit is contained in:
2026-07-17 19:00:47 +08:00
parent 4a2086c6f1
commit c858e8e311
6 changed files with 516 additions and 23 deletions
+113 -21
View File
@@ -4,11 +4,15 @@ import (
"fmt"
"net/url"
"strconv"
"strings"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
"ip_scan_go/internal/scan"
)
const appVersion = "V0.0.1"
@@ -31,6 +35,7 @@ type scanForm struct {
scanBtn *widget.Button
pingBtn *widget.Button
keypadBtn []*widget.Button
dispatcher *scan.Dispatcher
scanning bool
}
@@ -108,36 +113,108 @@ func (f *scanForm) buildControlRow() fyne.CanvasObject {
func (f *scanForm) toggleScan() {
if !f.scanning {
f.scanning = true
f.scanBtn.SetText("停止扫描")
f.pingBtn.Disable()
f.setInputsEnabled(false)
f.progress.SetValue(0)
f.output.Append("开始扫描... (TODO: 接入扫描逻辑)\n")
ips, err := scan.ParseIPs(f.ipList.Text)
if err != nil {
f.appendOutput("IP解析错误: " + err.Error() + "\n")
return
}
ports, err := scan.ParsePorts(f.portList.Text)
if err != nil {
f.appendOutput("端口解析错误: " + err.Error() + "\n")
return
}
if len(ips) == 0 || len(ports) == 0 {
f.appendOutput("请输入IP和端口\n")
return
}
f.startScan(false, ips, ports)
} else {
f.scanning = false
f.scanBtn.SetText("开始扫描")
f.pingBtn.Enable()
f.setInputsEnabled(true)
f.output.Append("已停止扫描\n")
f.stopScan()
}
}
func (f *scanForm) togglePing() {
if !f.scanning {
f.scanning = true
ips, err := scan.ParseIPs(f.ipList.Text)
if err != nil {
f.appendOutput("IP解析错误: " + err.Error() + "\n")
return
}
if len(ips) == 0 {
f.appendOutput("请输入IP\n")
return
}
f.startScan(true, ips, nil)
} else {
f.stopScan()
}
}
func (f *scanForm) startScan(pingOnly bool, ips []string, ports []int) {
f.scanning = true
if pingOnly {
f.pingBtn.SetText("停止Ping")
f.scanBtn.Disable()
f.setInputsEnabled(false)
f.progress.SetValue(0)
f.output.Append("开始Ping... (TODO: 接入扫描逻辑)\n")
} else {
f.scanning = false
f.pingBtn.SetText("仅Ping")
f.scanBtn.Enable()
f.setInputsEnabled(true)
f.output.Append("已停止Ping\n")
f.scanBtn.SetText("停止扫描")
f.pingBtn.Disable()
}
f.setInputsEnabled(false)
f.progress.SetValue(0)
timeout := time.Duration(parseIntEntry(f.timeout, 100)) * time.Millisecond
workers := parseIntEntry(f.threads, 64)
mode := "扫描"
if pingOnly {
mode = "Ping"
}
f.appendOutput(fmt.Sprintf("开始%s (IP:%d 线程:%d 超时:%s)\n", mode, len(ips), workers, timeout))
d := &scan.Dispatcher{
IPs: ips,
Ports: ports,
Timeout: timeout,
Workers: workers,
PingOnly: pingOnly,
OnResult: func(r scan.Result) {
fyne.Do(func() {
f.appendOutput(r.Text + "\n")
})
},
OnProgress: func(p scan.Progress) {
pct := float64(p.Done) / float64(p.Total)
fyne.Do(func() {
f.progress.SetValue(pct)
})
},
OnFinish: func() {
fyne.Do(func() {
f.resetAfterScan(pingOnly)
f.appendOutput(fmt.Sprintf("%s完成\n", mode))
})
},
}
f.dispatcher = d
go d.Start()
}
func (f *scanForm) stopScan() {
if f.dispatcher != nil {
f.dispatcher.Stop()
}
}
func (f *scanForm) resetAfterScan(pingOnly bool) {
f.scanning = false
if pingOnly {
f.pingBtn.SetText("仅Ping")
} else {
f.scanBtn.SetText("开始扫描")
}
f.scanBtn.Enable()
f.pingBtn.Enable()
f.setInputsEnabled(true)
f.dispatcher = nil
}
func (f *scanForm) setInputsEnabled(enabled bool) {
@@ -162,7 +239,14 @@ func (f *scanForm) setInputsEnabled(enabled bool) {
}
func (f *scanForm) saveOutput() {
f.output.Append("(TODO: 保存输出到文件)\n")
f.appendOutput("(TODO: 保存输出到文件)\n")
}
func (f *scanForm) appendOutput(text string) {
f.output.Append(text)
f.output.CursorRow = strings.Count(f.output.Text, "\n")
f.output.CursorColumn = 0
f.output.Refresh()
}
func (f *scanForm) openURL(urlStr string) {
@@ -185,3 +269,11 @@ func newIntEntry(val, min, max int) *widget.Entry {
}
return e
}
func parseIntEntry(e *widget.Entry, fallback int) int {
n, err := strconv.Atoi(e.Text)
if err != nil || n <= 0 {
return fallback
}
return n
}