话不多说先上测试结果

  • machine: MacBook Pro M1
  • body.json size: 2.34KiB
  • max cost: cpu=440% memory=90MiB
  • command: tcpkali -c 200 -r 20000 -T 20s -f body.json --ws 127.0.0.1:3000/connect
lxzan/gws
Destination: [127.0.0.1]:3000
Interface lo0 address [127.0.0.1]:0
Using interface lo0 to connect to [127.0.0.1]:3000
Ramped up to 200 connections.
Total data sent:     28864.1 MiB (30266158036 bytes)
Total data received: 28812.3 MiB (30211911226 bytes)
Bandwidth per channel: 120.909⇅ Mbps (15113.7 kBps)
Aggregate bandwidth: 12080.082↓, 12101.773↑ Mbps
Packet rate estimate: 1098496.2↓, 1105141.9↑ (8↓, 14↑ TCP MSS/op)
Test duration: 20.0078 s.
gorilla/websocket
Destination: [127.0.0.1]:3000
Interface lo0 address [127.0.0.1]:0
Using interface lo0 to connect to [127.0.0.1]:3000
Ramped up to 200 connections.
Total data sent:     15043.6 MiB (15774402996 bytes)
Total data received: 14990.0 MiB (15718181647 bytes)
Bandwidth per channel: 62.972⇅ Mbps (7871.5 kBps)
Aggregate bandwidth: 6285.944↓, 6308.428↑ Mbps
Packet rate estimate: 589201.4↓, 579598.1↑ (5↓, 12↑ TCP MSS/op)
Test duration: 20.0042 s.

亮点

  • 无依赖
  • 不需要开启额外协程监听消息, 处理各种事件
  • 读写消息不返回错误, 它们在gws内部被适当的处理了
  • 事件驱动
  • 通过了 autobahn-testsuite 所有的WebSocket Protocol测试用例

安装

go get -v github.com/lxzan/gws@latest

核心接口

type Event interface {
    OnOpen(socket *Conn)
    OnError(socket *Conn, err error)
    OnClose(socket *Conn, code uint16, reason []byte)
    OnPing(socket *Conn, payload []byte)
    OnPong(socket *Conn, payload []byte)
    OnMessage(socket *Conn, message *Message)
}

快速开始

package main

import (
    "fmt"
    "github.com/lxzan/gws"
    "net/http"
)

func main() {
    var config = &gws.Config{
        CompressEnabled:   true,
        CheckTextEncoding: true,
        MaxContentLength:  32 * 1024 * 1024,
        ResponseHeader:    http.Header{"Server": []string{"gws"}},
    }
    var handler = new(WebSocket)
    http.HandleFunc("/connect", func(writer http.ResponseWriter, request *http.Request) {
        socket, err := gws.Accept(writer, request, handler, config)
        if err != nil {
            return
        }
        socket.Listen()
    })

    _ = http.ListenAndServe(":3000", nil)
}

type WebSocket struct{}

func (c *WebSocket) OnClose(socket *gws.Conn, code uint16, reason []byte) {
    fmt.Printf("onclose: code=%d, payload=%s\n", code, string(reason))
}

func (c *WebSocket) OnError(socket *gws.Conn, err error) {
    fmt.Printf("onerror: err=%s\n", err.Error())
}

func (c *WebSocket) OnOpen(socket *gws.Conn) {
    println("connected")
}

func (c *WebSocket) OnPing(socket *gws.Conn, payload []byte) {
    fmt.Printf("onping: payload=%s\n", string(payload))
    socket.WritePong(payload)
}

func (c *WebSocket) OnPong(socket *gws.Conn, payload []byte) {}

func (c *WebSocket) OnMessage(socket *gws.Conn, message *gws.Message) {
    socket.WriteMessage(message.Typ(), message.Bytes())
    message.Close()
}

测试

docker run -it --rm \
    -v ${PWD}/config:/config \
    -v ${PWD}/reports:/reports \
    crossbario/autobahn-testsuite \
    wstest -m fuzzingclient -s /config/fuzzingclient.json

image.png


codebeast
51 声望0 粉丝