Skip to content

Latest commit

 

History

History
201 lines (160 loc) · 3.5 KB

c1000k.md

File metadata and controls

201 lines (160 loc) · 3.5 KB

如何发起一百万个连接

四元组

[源IP] + [源端口] + [目标IP] + [目标端口]

五元组

[协议] + [源IP] + [源端口] + [目标IP] + [目标端口]
  • 由于目标IP、目标端口是固定的,可以通过构造不同的源IP和源端口用于发起连接,从而达到建立百万连接的目的

构造源IP

  • 查看IP信息
ifconfig

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.11  netmask 255.255.255.0  broadcast 192.168.2.255

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        
  • 添加IP(添加20个即可,每个ip发起52000个连接可以达到百万连接了)
sudo ip address add 192.168.2.12 dev eth0
sudo ip address add 192.168.2.13 dev eth0
...

服务端

示例代码

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/ikilobyte/netman/iface"
	"github.com/ikilobyte/netman/server"
)

type Ping struct {
}

func (p *Ping) Do(request iface.IRequest) {
	//fmt.Printf("recv PING %d %s\n", request.GetConnect().GetID(), time.Now().String())
}

func main() {

	fmt.Println(os.Getpid())
	s := server.New("0.0.0.0", 6565, server.WithMaxBodyLength(0))

	go func() {
		ticker := time.NewTicker(time.Second * 5)
		for {
			select {
			case <-ticker.C:
				fmt.Printf("total connection %d\n", s.TotalConnect())
			}
		}
	}()

	s.AddRouter(0, new(Ping))
	s.Start()
}

启动服务端

ulimit -n 1200000
go run .

客户端

示例代码

package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"sync"
	"time"

	"github.com/ikilobyte/netman/util"
)

var device = flag.String("device", "eth0", "网卡名称")
var total = flag.Int("total", 10, "每个IP发起的数量")
var server = flag.String("server", "", "服务器地址")

func main() {
	flag.Parse()

	if *server == "" {
		log.Panicln("请传入服务器地址")
	}

	ips := getIps(*device)
	if len(ips) <= 0 {
		log.Panicln("没有可用的IP地址")
	}
	fmt.Printf("ips %v total %d\n", ips, len(ips))
	time.Sleep(time.Second * 10)
	for _, ip := range ips {
		go connect(ip)
	}

	select {}
}

func getIps(value string) []net.IP {
	result := make([]net.IP, 0)

	name, err := net.InterfaceByName(value)
	if err != nil {
		panic(err)
	}

	addrs, err := name.Addrs()
	if err != nil {
		panic(err)
	}
	for _, addr := range addrs {
		ipNet, ok := addr.(*net.IPNet)
		if ok && !ipNet.IP.IsLoopback() {
			if ipNet.IP.To4() != nil {
				result = append(result, ipNet.IP.To4())
			}
		}
	}

	return result
}

func connect(ip net.IP) {
	var wg sync.WaitGroup

	c := make(chan net.Conn, 512)
	go func() {
		list := make([]net.Conn, 0, 51000)
		ticker := time.NewTicker(time.Second * 5)
		for {
			select {
			case <-ticker.C:
				fmt.Printf("ip %v connect %d\n", ip, len(list))
			case conn := <-c:
				list = append(list, conn)
			}
		}
	}()

	packer := util.NewDataPacker()

	// 每个IP地址发起的连接数
	for i := 0; i < *total; i++ {
		wg.Add(1)
		go func(port int) {
			defer wg.Done()

			conn, err := net.DialTCP("tcp",
				&net.TCPAddr{IP: ip, Port: port + 10000},
				&net.TCPAddr{IP: net.ParseIP(*server), Port: 6565},
			)
			if err != nil {
				fmt.Printf("connect err by port %d err %v\n", port, err)
				return
			}

			c <- conn
			for {
				pack, _ := packer.Pack(0, []byte("PING"))
				conn.Write(pack)
				time.Sleep(time.Second * 10)
			}
		}(i)
		time.Sleep(time.Millisecond * 10)
	}
	wg.Wait()
}

启动客户端

ulimit -n 1200000
go run . --server xxx.xx.xx.xx --device xxx