#TCP を使用して接続する場合、相手のマシン#を知る必要があります。 ##ip:port通常のハンドシェイク
成功した場合のプロセスは次のとおりです。 正常であれば、failed となります。 , if接続先##がクローズされている場合は次のようになります。 ポートは開いていますが、 はファイアウォールによってブロックされています。 処理は次のとおりです。 #コード TCP に net.Dial を使用します。繋がり#########。 ちょうど2つの状況 成功: 接続を返します。 #失敗しました:エラー != nil 比較的、最初はあまり大胆ではないかもしれません。最初にプロトタイプを書いてください。 、パフォーマンスを考慮せずに。 #コード 実行結果 ##ただし、このプロセスは非常に時間がかかります。 因为 上述是通过循环去一个个连接 所以,多线程如下。 代码 执行结果 実際には、各 したがって、#最長のスレッドが終了するまでにかかる時間 がプログラムの終了時間となります。 大丈夫です。20 秒間で 60,000 以上のポートをスキャンできました。 ! ! 上記は 単純かつ粗雑です このメソッドは、ip:port Go では、理論的には数十万のコルーチンを開くことは問題ありませんが、それでもある程度の プレッシャーが存在します ## ##の。 所以我们应该采用一种相对节约的方式进行精简代码,一般采用线程池方式。 本次使用的线程池包: 地址:https://github.com/loveleshsharma/gohive 简单介绍 代码 执行结果 我设置的线程池大小是7w个,所以也是一下子开启6w多个协程的,但是我们已经可以进行线程大小约束了。 このようなリクエストがあるとします。 # #つまり、 スレッド プールを 500,000 に制御すると、状況はさらに改善される可能性があります。 ただし、Go では通常、スレッド プールを chan この記事は、楽しい記事です、詳しく見てみましょうそれ 楽しいこと。 実際には、 ここでは例を挙げません。 #主に 3 つのメソッド # を使用して関数を実装します。 通常の バージョン、同時実行性がなく、非常に遅い。 複数のコルーチン バージョン、同時実行性、高パフォーマンスですが、コルーチンが多すぎるとクラッシュする可能性があります。 コルーチン プール バージョン、同時実行性、高パフォーマンス、制御可能なコルーチンの数。 通常、基礎がOKであれば、さらに 推奨を使用します。コルーチンプールの方法。
接続に失敗しました
別の可能性もあります。
Go では通常、
。
通常版
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:port
をスキャンするために 6W の複数のスレッドが同時に開かれます。 #スレッド プールのバージョン
ごとにコルーチンを作成します。
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
が 100 個あり、それぞれが必要とします。 ip
単純かつ粗雑な方法でスレッドを開く場合は、ポートを開きます。100 65535=6552300
#、600 w スレッドを超えると依然として大量のメモリが消費され、スレッド プール方式が使用されるとシステムがクラッシュする可能性があります。 。 と組み合わせて使用する必要があることが 1 つあります。 . 必要かもしれない 基礎としては悪くない。
概要
net.DialTimeout
を通じて接続することもできます。 ip:port
で、このタイムアウトを設定できます。たとえば、5秒タイムアウトした場合、ポートが開いていないと判断されます。
以上がGo 言語を使用して簡単な TCP ポート スキャナーを構築する方法を段階的に説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。