Files
chain33-im/benchmarks/client_tcp/main.go
2022-03-17 15:55:27 +08:00

235 lines
5.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
// Start Commond eg: ./client 1 1000 localhost:3101
// first parameterbeginning userId
// second parameter: amount of clients
// third parameter: comet tcp-server addr
import (
"bufio"
"encoding/binary"
"flag"
"fmt"
"log"
"math/rand"
"net"
"os"
"runtime"
"strconv"
"sync/atomic"
"time"
"github.com/golang/protobuf/proto"
comet "gitlab.33.cn/chat/im/api/comet/grpc"
)
const (
rawHeaderLen = uint16(16)
heart = 5 * time.Second
)
type Proto struct {
PackLen int32 // package length
HeaderLen int16 // header length
Ver int16 // protocol version
Operation int32 // operation for request
Seq int32 // sequence number chosen by client
Body []byte // body
}
var (
countDown int64
aliveCount int64
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.Parse()
begin, err := strconv.Atoi(os.Args[1])
if err != nil {
panic(err)
}
num, err := strconv.Atoi(os.Args[2])
if err != nil {
panic(err)
}
go result()
for i := begin; i < begin+num; i++ {
go client(int64(i))
}
// signal
var exit chan bool
<-exit
}
func result() {
var (
lastTimes int64
interval = int64(5)
)
for {
nowCount := atomic.LoadInt64(&countDown)
nowAlive := atomic.LoadInt64(&aliveCount)
diff := nowCount - lastTimes
lastTimes = nowCount
fmt.Println(fmt.Sprintf("%s alive:%d down:%d down/s:%d", time.Now().Format("2006-01-02 15:04:05"), nowAlive, nowCount, diff/interval))
time.Sleep(time.Second * time.Duration(interval))
}
}
func client(mid int64) {
for {
startClient(mid)
time.Sleep(time.Duration(rand.Intn(10)) * time.Second)
}
}
func startClient(key int64) {
time.Sleep(time.Duration(rand.Intn(10)) * time.Second)
atomic.AddInt64(&aliveCount, 1)
quit := make(chan bool, 1)
defer func() {
close(quit)
atomic.AddInt64(&aliveCount, -1)
}()
// connnect to server
conn, err := net.Dial("tcp", os.Args[3])
if err != nil {
log.Printf("net.Dial(%s) error(%v)", os.Args[3], err)
return
}
seq := int32(0)
wr := bufio.NewWriter(conn)
rd := bufio.NewReader(conn)
authMsg := &comet.AuthMsg{
AppId: "echo",
Token: "fdasfdsaf",
}
p := new(Proto)
p.Ver = 1
p.Operation = int32(comet.Op_Auth)
p.Seq = seq
p.Body, _ = proto.Marshal(authMsg)
if err = tcpWriteProto(wr, p); err != nil {
log.Printf("tcpWriteProto() error(%v)", err)
return
}
if err = tcpReadProto(rd, p); err != nil {
log.Printf("tcpReadProto() error(%v)", err)
return
}
log.Printf("key:%d auth ok, proto: %v", key, p)
seq++
// writer
go func() {
hbProto := new(Proto)
for {
// heartbeat
hbProto.Operation = int32(comet.Op_Heartbeat)
hbProto.Seq = seq
hbProto.Body = nil
if err = tcpWriteProto(wr, hbProto); err != nil {
log.Printf("key:%d tcpWriteProto() error(%v)", key, err)
return
}
log.Printf("key:%d Write heartbeat", key)
time.Sleep(heart)
seq++
select {
case <-quit:
return
default:
}
}
}()
// reader
for {
if err = tcpReadProto(rd, p); err != nil {
log.Printf("key:%d tcpReadProto() error(%v)", key, err)
quit <- true
return
}
if p.Operation == int32(comet.Op_AuthReply) {
log.Printf("key:%d auth success", key)
} else if p.Operation == int32(comet.Op_HeartbeatReply) {
log.Printf("key:%d receive heartbeat reply", key)
if err = conn.SetReadDeadline(time.Now().Add(heart + 60*time.Second)); err != nil {
log.Printf("conn.SetReadDeadline() error(%v)", err)
quit <- true
return
}
} else {
log.Printf("key:%d op:%d msg: %s", key, p.Operation, string(p.Body))
atomic.AddInt64(&countDown, 1)
}
}
}
func tcpWriteProto(wr *bufio.Writer, proto *Proto) (err error) {
// write
if err = binary.Write(wr, binary.BigEndian, uint32(rawHeaderLen)+uint32(len(proto.Body))); err != nil {
return
}
if err = binary.Write(wr, binary.BigEndian, rawHeaderLen); err != nil {
return
}
if err = binary.Write(wr, binary.BigEndian, proto.Ver); err != nil {
return
}
if err = binary.Write(wr, binary.BigEndian, proto.Operation); err != nil {
return
}
if err = binary.Write(wr, binary.BigEndian, proto.Seq); err != nil {
return
}
if proto.Body != nil {
if err = binary.Write(wr, binary.BigEndian, proto.Body); err != nil {
return
}
}
err = wr.Flush()
return
}
func tcpReadProto(rd *bufio.Reader, proto *Proto) (err error) {
var (
packLen int32
headerLen int16
)
// read
if err = binary.Read(rd, binary.BigEndian, &packLen); err != nil {
return
}
if err = binary.Read(rd, binary.BigEndian, &headerLen); err != nil {
return
}
if err = binary.Read(rd, binary.BigEndian, &proto.Ver); err != nil {
return
}
if err = binary.Read(rd, binary.BigEndian, &proto.Operation); err != nil {
return
}
if err = binary.Read(rd, binary.BigEndian, &proto.Seq); err != nil {
return
}
var (
n, t int
bodyLen = int(packLen - int32(headerLen))
)
if bodyLen > 0 {
proto.Body = make([]byte, bodyLen)
for {
if t, err = rd.Read(proto.Body[n:]); err != nil {
return
}
if n += t; n == bodyLen {
break
}
}
} else {
proto.Body = nil
}
return
}