端口扫描应用开发:主机列表管理与命令实现
立即解锁
发布时间: 2025-09-14 00:08:01 阅读量: 2 订阅数: 35 AIGC 

### 端口扫描应用开发:主机列表管理与命令实现
在开发端口扫描应用时,我们需要实现主机列表管理的功能。下面将详细介绍如何创建主机列表管理的包、编写相关代码以及实现命令行工具的测试。
#### 1. 创建扫描包
首先,我们要创建一个名为 `scan` 的包来实现主机列表管理的业务逻辑。具体操作步骤如下:
1. 进入应用的根目录,创建 `scan` 目录并切换到该目录:
```bash
$ cd $HOME/pragprog.com/rggo/cobra/pScan
$ mkdir scan
$ cd scan
```
2. 创建并编辑 `hostsList.go` 文件,定义包名和导入所需的包:
```go
// Package scan provides types and functions to perform TCP port
// scans on a list of hosts
package scan
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"sort"
)
```
3. 定义两个错误变量,分别表示主机已存在和主机不存在:
```go
var (
ErrExists = errors.New("Host already in the list")
ErrNotExists = errors.New("Host not in the list")
)
```
4. 定义 `HostsList` 结构体来表示主机列表:
```go
// HostsList represents a list of hosts to run port scan
type HostsList struct {
Hosts []string
}
```
5. 为 `HostsList` 结构体定义方法:
- `search` 方法:用于在列表中搜索主机:
```go
// search searches for hosts in the list
func (hl *HostsList) search(host string) (bool, int) {
sort.Strings(hl.Hosts)
i := sort.SearchStrings(hl.Hosts, host)
if i < len(hl.Hosts) && hl.Hosts[i] == host {
return true, i
}
return false, -1
}
```
- `Add` 方法:用于向列表中添加主机:
```go
// Add adds a host to the list
func (hl *HostsList) Add(host string) error {
if found, _ := hl.search(host); found {
return fmt.Errorf("%w: %s", ErrExists, host)
}
hl.Hosts = append(hl.Hosts, host)
return nil
}
```
- `Remove` 方法:用于从列表中删除主机:
```go
// Remove deletes a host from the list
func (hl *HostsList) Remove(host string) error {
if found, i := hl.search(host); found {
hl.Hosts = append(hl.Hosts[:i], hl.Hosts[i+1:]...)
return nil
}
return fmt.Errorf("%w: %s", ErrNotExists, host)
}
```
- `Load` 方法:用于从文件中加载主机列表:
```go
// Load obtains hosts from a hosts file
func (hl *HostsList) Load(hostsFile string) error {
f, err := os.Open(hostsFile)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
hl.Hosts = append(hl.Hosts, scanner.Text())
}
return nil
}
```
- `Save` 方法:用于将主机列表保存到文件中:
```go
// Save saves hosts to a hosts file
func (hl *HostsList) Save(hostsFile string) error {
output := ""
for _, h := range hl.Hosts {
output += fmt.Sprintln(h)
}
return ioutil.WriteFile(hostsFile, []byte(output), 0644)
}
```
#### 2. 编写测试用例
为了确保 `scan` 包的功能正常,我们需要编写测试用例。具体步骤如下:
1. 保存 `hostsList.go` 文件,创建并编辑 `hostsList_test.go` 文件,定义包名和导入所需的包:
```go
package scan_test
import (
"errors"
"io/ioutil"
"os"
"testing"
"pragprog.com/rggo/cobra/pScan/scan"
)
```
2. 编写 `TestAdd` 函数来测试 `Add` 方法:
```go
func TestAdd(t *testing.T) {
testCases := []struct {
name string
host string
expectLen int
expectErr error
}{
{"AddNew", "host2", 2, nil},
{"AddExisting", "host1", 1, scan.ErrExists},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
hl := &scan.HostsList{}
// Initialize list
if err := hl.Add("host1"); err != nil {
t.Fatal(err)
}
err := hl.Add(tc.host)
if tc.expectErr != nil {
if err == nil {
t.Fatalf("Expected error, got nil instead\n")
}
if !errors.Is(err, tc.expectErr) {
t.Errorf("Expected error %q, got %q instead\n",
tc.expectErr, err)
}
return
}
if err != nil {
t.Fatalf("Expected no error, got %q instead\n", err)
}
if len(hl.Hosts) != tc.expectLen {
t.Errorf("Expected list length %d, got %d instead\n",
tc.expectLen, len(hl.Hosts))
}
if hl.Hosts[1] != tc.host {
t.Errorf("Expected host name %q as index 1, got %q instead\n",
tc.host, hl.Hosts[1])
}
})
}
}
```
3. 编写 `TestRemove` 函数来测试 `Remove` 方法:
```go
func TestRemove(t *testing.T) {
testCases := []struct {
name string
host string
expectLen int
expectErr error
}{
{"RemoveExisting", "host1", 1, nil},
{"RemoveNotFound", "host3", 1, scan.ErrNotExists},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
hl := &scan.HostsList{}
// Initialize list
for _, h := range []string{"host1", "host2"} {
if err := hl.Add(h); err != nil {
t.Fatal(err)
}
}
err := hl.Remove(tc.host)
if tc.expectErr != nil {
if err == nil {
t.Fatalf("Expected error, got nil instead\n")
}
if !errors.Is(err, tc.expectErr) {
t.Errorf("Expected error %q, got %q instead\n",
tc.expectErr, err)
}
return
}
if err != nil {
t.Fatalf("Expected no error, got %q instead\n", err)
}
if len(hl.Hosts) != tc.expectLen {
t.Errorf("Expected list length %d, got %d instead\n",
tc.expectLen, len(hl.Hosts))
}
if hl.Hosts[0] == tc.host {
t.Errorf("Host name %q should not be in the list\n", tc.host)
}
```
0
0
复制全文
相关推荐









