ㅋㅋㅋ
에 성공하면 과정은 다음과 같습니다. 는 정상이며, 실패가 있습니다. 연결된 당사자에 의해 가 종료된 경우 프로세스는 다음과 같습니다. 또 다른 가능성이 있습니다. 포트는 열려 있지만 방화벽 차단, 과정은 다음과 같습니다. Code Go에서는 일반적으로 을 사용하여 단지 두 가지 상황 Success이 있습니다. conn으로 돌아갑니다. 실패: 비교적으로 말하면 처음에는 너무 대담하지 않을 수도 있고, 성능을 고려하지 않고 모두 프로토타입을 먼저 작성합니다. Code 실행 결과 하지만 이 프로세스는 매우 느립니다. 因为 上述是通过循环去一个个连接 所以,多线程如下。 代码 执行结果 실제로 6W 다중 스레드가 동시에 열려 각 所以耗时最长的线程结束的时间,就是程序结束的时间。 感觉还行,20s+扫描完6w多个端口!!! 上面我们简单粗暴的方式为每个 끝나는 데 가장 긴 스레드 이 프로그램이 끝나는 시간입니다. feeling 나쁘지 않은데, 20초 안에 60,000개의 포트가 스캔되었습니다! ! ! 🎜Above us🎜🎜🎜 각 🎜🎜 所以我们应该采用一种相对节约的方式进行精简代码,一般采用线程池方式。 本次使用的线程池包: 地址:https://github.com/loveleshsharma/gohive 简单介绍 代码 执行结果 我设置的线程池大小是7w个,所以也是一下子开启6w多个协程的,但是我们已经可以进行线程大小约束了。 지금 그러한 요청이 있다고 가정하면 100개가 있습니다. 那就是 将线程池控制在50w个,或许情况就会好很多。 但是有一点的是,在Go中,线程池通常需要配合 🎜바로 그거예요🎜🎜100+65535=6552300🎜 🎜, 600w 이상의 스레드는 여전히 많은 메모리를 소비하며 스레드 풀 방식을 사용하면 시스템이 충돌할 수 있습니다. 🎜🎜 🎜will 스레드 풀을 500,000으로 제어하면 상황이 훨씬 좋아질 수 있습니다. 🎜🎜 🎜하지만 한 가지 점은 Go에서 스레드 풀은 일반적으로 🎜🎜 이 기사는 재미있는 기사에 더 가깝고 재미있는 것들에 대해 알아볼 수 있습니다. 실제로 , 이 시간 제한을 설정할 수 있습니다. 예를 들어 시간 제한이 5초이면 포트가 열려 있지 않은 것으로 판단됩니다. . 여기에서는 예를 들어주지 않겠습니다. 우리는 함수 구현을 위해 주로 세 가지 방법 Normal 다중 코루틴 코루틴 풀버전, 동시성, 고성능 및 제어 가능한 코루틴 수. 보통은 기본만 괜찮다면 코루틴 풀 방식을 사용하는 것이 더추천입니다.
연결 실패
방화벽이 있는 경우
본질을 이해한 후 코딩을 시작할 수 있습니다. net.Dial
TCP 연결을 만듭니다.
err != nil
. 일반 버전
package main
import (
"fmt"
"net"
)
func main() {
var ip = "192.168.43.34"
for i := 21; i <= 120; i++ {
var address = fmt.Sprintf("%s:%d", ip, i)
conn, err := net.Dial("tcp", address)
if err != nil {
fmt.Println(address, "是关闭的")
continue
}
conn.Close()
fmt.Println(address, "打开")
}
}
net.Dial
如果连接的是未开放的端口,一个端口可能就是20s+,所以,我们为什么学习多线程懂了把!!!多线程版
ip:port
的,那我们就知道了,在一个个连接的位置,让多个人去干就好了。package main
import (
"fmt"
"net"
"sync"
"time"
)
func main() {
var begin =time.Now()
//wg
var wg sync.WaitGroup
//ip
var ip = "192.168.99.112"
//var ip = "192.168.43.34"
//循环
for j := 21; j <= 65535; j++ {
//添加wg
wg.Add(1)
go func(i int) {
//释放wg
defer wg.Done()
var address = fmt.Sprintf("%s:%d", ip, i)
//conn, err := net.DialTimeout("tcp", address, time.Second*10)
conn, err := net.Dial("tcp", address)
if err != nil {
//fmt.Println(address, "是关闭的", err)
return
}
conn.Close()
fmt.Println(address, "打开")
}(j)
}
//等待wg
wg.Wait()
var elapseTime = time.Now().Sub(begin)
fmt.Println("耗时:", elapseTime)
}
ip:포트
ip:port
。线程池版
ip:port
. 🎜스레드 풀 버전🎜
ip:port
🎜🎜 둘 다 코루틴을 생성합니다. 🎜🎜🎜🎜Go에서는 수십만 개의 코루틴을 여는 것이 이론적으로는 문제가 없지만 여전히 🎜🎜🎜압력🎜🎜🎜이 있습니다. 🎜🎜gohive
package main
//线程池方式
import (
"fmt"
"github.com/loveleshsharma/gohive"
"net"
"sync"
"time"
)
//wg
var wg sync.WaitGroup
//地址管道,100容量
var addressChan = make(chan string, 100)
//工人
func worker() {
//函数结束释放连接
defer wg.Done()
for {
address, ok := <-addressChan
if !ok {
break
}
//fmt.Println("address:", address)
conn, err := net.Dial("tcp", address)
//conn, err := net.DialTimeout("tcp", address, 10)
if err != nil {
//fmt.Println("close:", address, err)
continue
}
conn.Close()
fmt.Println("open:", address)
}
}
func main() {
var begin = time.Now()
//ip
var ip = "192.168.99.112"
//线程池大小
var pool_size = 70000
var pool = gohive.NewFixedSizePool(pool_size)
//拼接ip:端口
//启动一个线程,用于生成ip:port,并且存放到地址管道种
go func() {
for port := 1; port <= 65535; port++ {
var address = fmt.Sprintf("%s:%d", ip, port)
//将address添加到地址管道
//fmt.Println("<-:",address)
addressChan <- address
}
//发送完关闭 addressChan 管道
close(addressChan)
}()
//启动pool_size工人,处理addressChan种的每个地址
for work := 0; work < pool_size; work++ {
wg.Add(1)
pool.Submit(worker)
}
//等待结束
wg.Wait()
//计算时间
var elapseTime = time.Now().Sub(begin)
fmt.Println("耗时:", elapseTime)
}
ip
ip
,需要扫描每个ip
开放的端口,如果采用简单粗暴开线程的方式.100+65535=6552300
,600多w个线程,还是比较消耗内存的,可能系统就会崩溃,如果采用线程池方式。chan
, 각 ip
chan
🎜🎜사용하려면 좋은 기초가 필요할 수 있습니다. 🎜🎜요약
net.DialTimeout
net.DialTimeout
连接ip:port
Connectionip:port
을 사용합니다.
위 내용은 手把手教你用Go语言打造一款简易TCP端口扫描器의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!