gws

package module
v1.8.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2024 License: Apache-2.0 Imports: 24 Imported by: 17

README

中文

GWS

logo

Simple, Fast, Reliable WebSocket Server & Client

awesome codecov go-test go-reportcard license go-version

Introduction

GWS (Go WebSocket) is a very simple, fast, reliable and feature-rich WebSocket implementation written in Go. It is designed to be used in highly-concurrent environments, and it is suitable for building API, Proxy, Game, Live Video, Message, etc. It supports both server and client side with a simple API which mean you can easily write a server or client by yourself.

GWS developed base on Event-Driven model. every connection has a goroutine to handle the event, and the event is able to be processed in a non-blocking way.

Why GWS

  • Simplicity and Ease of Use

    • User-Friendly: Simple and clear WebSocket Event API design makes server-client interaction easy.
    • Code Efficiency: Minimizes the amount of code needed to implement complex WebSocket solutions.
  • High-Performance

    • High IOPS Low Latency: Designed for rapid data transmission and reception, ideal for time-sensitive applications.
    • Low Memory Usage: Highly optimized memory multiplexing system to minimize memory usage and reduce your cost of ownership.
  • Reliability and Stability

    • Robust Error Handling: Advanced mechanisms to manage and mitigate errors, ensuring continuous operation.
    • Well-Developed Test Cases: Passed all Autobahn test cases, fully compliant with RFC 7692. Unit test coverage is almost 100%, covering all conditional branches.

Benchmark

IOPS (Echo Server)

GOMAXPROCS=4, Connection=1000, CompressEnabled=false

performance

gorilla and nhooyr not using stream api

GoBench

goos: linux
goarch: amd64
pkg: github.com/lxzan/gws
cpu: AMD Ryzen 5 PRO 4650G with Radeon Graphics
BenchmarkConn_WriteMessage/compress_disabled-8         	 7252513	     165.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkConn_WriteMessage/compress_enabled-8          	   97394	     10391 ns/op	     349 B/op	       0 allocs/op
BenchmarkConn_ReadMessage/compress_disabled-8          	 7812108	     152.3 ns/op	      16 B/op	       0 allocs/op
BenchmarkConn_ReadMessage/compress_enabled-8           	  368712	      3248 ns/op	     108 B/op	       0 allocs/op
PASS

Index

Feature

  • Event API
  • Broadcast
  • Dial via Proxy
  • Context-Takeover
  • Passed Autobahn Test Cases Server / Client
  • Concurrent & Asynchronous Non-Blocking Write

Attention

  • The errors returned by the gws.Conn export methods are ignorable, and are handled internally.
  • Transferring large files with gws tends to block the connection.
  • If HTTP Server is reused, it is recommended to enable goroutine, as blocking will prevent the context from being GC.

Install

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

Event

type Event interface {
    OnOpen(socket *Conn)                        // connection is established
    OnClose(socket *Conn, err error)            // received a close frame or input/output error occurs
    OnPing(socket *Conn, payload []byte)        // received a ping frame
    OnPong(socket *Conn, payload []byte)        // received a pong frame
    OnMessage(socket *Conn, message *Message)   // received a text/binary frame
}

Quick Start

package main

import "github.com/lxzan/gws"

func main() {
	gws.NewServer(&gws.BuiltinEventHandler{}, nil).Run(":6666")
}

Best Practice

package main

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

const (
	PingInterval = 5 * time.Second
	PingWait     = 10 * time.Second
)

func main() {
	upgrader := gws.NewUpgrader(&Handler{}, &gws.ServerOption{
		ParallelEnabled:  true,                                 // Parallel message processing
		Recovery:          gws.Recovery,                         // Exception recovery
		PermessageDeflate: gws.PermessageDeflate{Enabled: true}, // Enable compression
	})
	http.HandleFunc("/connect", func(writer http.ResponseWriter, request *http.Request) {
		socket, err := upgrader.Upgrade(writer, request)
		if err != nil {
			return
		}
		go func() {
			socket.ReadLoop() // Blocking prevents the context from being GC.
		}()
	})
	http.ListenAndServe(":6666", nil)
}

type Handler struct{}

func (c *Handler) OnOpen(socket *gws.Conn) {
	_ = socket.SetDeadline(time.Now().Add(PingInterval + PingWait))
}

func (c *Handler) OnClose(socket *gws.Conn, err error) {}

func (c *Handler) OnPing(socket *gws.Conn, payload []byte) {
	_ = socket.SetDeadline(time.Now().Add(PingInterval + PingWait))
	_ = socket.WritePong(nil)
}

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

func (c *Handler) OnMessage(socket *gws.Conn, message *gws.Message) {
	defer message.Close()
	socket.WriteMessage(message.Opcode, message.Bytes())
}

More Examples

KCP

  • server
package main

import (
	"log"
	"github.com/lxzan/gws"
	kcp "github.com/xtaci/kcp-go"
)

func main() {
	listener, err := kcp.Listen(":6666")
	if err != nil {
		log.Println(err.Error())
		return
	}
	app := gws.NewServer(&gws.BuiltinEventHandler{}, nil)
	app.RunListener(listener)
}
  • client
package main

import (
	"github.com/lxzan/gws"
	kcp "github.com/xtaci/kcp-go"
	"log"
)

func main() {
	conn, err := kcp.Dial("127.0.0.1:6666")
	if err != nil {
		log.Println(err.Error())
		return
	}
	app, _, err := gws.NewClientFromConn(&gws.BuiltinEventHandler{}, nil, conn)
	if err != nil {
		log.Println(err.Error())
		return
	}
	app.ReadLoop()
}

Proxy

Dial via proxy, using socks5 protocol.

package main

import (
	"crypto/tls"
	"github.com/lxzan/gws"
	"golang.org/x/net/proxy"
	"log"
)

func main() {
	socket, _, err := gws.NewClient(new(gws.BuiltinEventHandler), &gws.ClientOption{
		Addr:      "wss://example.com/connect",
		TlsConfig: &tls.Config{InsecureSkipVerify: true},
		NewDialer: func() (gws.Dialer, error) {
			return proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, nil)
		},
		PermessageDeflate: gws.PermessageDeflate{
			Enabled:               true,
			ServerContextTakeover: true,
			ClientContextTakeover: true,
		},
	})
	if err != nil {
		log.Println(err.Error())
		return
	}
	socket.ReadLoop()
}

Broadcast

Create a Broadcaster instance, call the Broadcast method in a loop to send messages to each client, and close the broadcaster to reclaim memory. The message is compressed only once.

func Broadcast(conns []*gws.Conn, opcode gws.Opcode, payload []byte) {
    var b = gws.NewBroadcaster(opcode, payload)
    defer b.Close()
    for _, item := range conns {
        _ = b.Broadcast(item)
    }
}

WriteWithTimeout

SetDeadline covers most of the scenarios, but if you want to control the timeout for each write, you need to encapsulate the WriteWithTimeout function, the creation and destruction of the timer will incur some overhead.

func WriteWithTimeout(socket *gws.Conn, p []byte, timeout time.Duration) error {
	var sig = atomic.Uint32{}
	var timer = time.AfterFunc(timeout, func() {
		if sig.CompareAndSwap(0, 1) {
			socket.WriteClose(1000, []byte("write timeout"))
		}
	})
	var err = socket.WriteMessage(gws.OpcodeText, p)
	if sig.CompareAndSwap(0, 1) {
		timer.Stop()
	}
	return err
}

Pub / Sub

Use the event_emitter package to implement the publish-subscribe model. Wrap gws.Conn in a structure and implement the GetSubscriberID method to get the subscription ID, which must be unique. The subscription ID is used to identify the subscriber, who can only receive messages on the subject of his subscription.

This example is useful for building chat rooms or push messages using gws. This means that a user can subscribe to one or more topics via websocket, and when a message is posted to that topic, all subscribers will receive the message.

package main

import (
	"github.com/lxzan/event_emitter"
	"github.com/lxzan/gws"
)

type Socket struct{ *gws.Conn }

func (c *Socket) GetSubscriberID() int64 {
	userId, _ := c.Session().Load("userId")
	return userId.(int64)
}

func (c *Socket) GetMetadata() event_emitter.Metadata {
	return c.Conn.Session()
}

func Sub(em *event_emitter.EventEmitter[*Socket], topic string, socket *Socket) {
	em.Subscribe(socket, topic, func(subscriber *Socket, msg any) {
		_ = msg.(*gws.Broadcaster).Broadcast(subscriber.Conn)
	})
}

func Pub(em *event_emitter.EventEmitter[*Socket], topic string, op gws.Opcode, msg []byte) {
	var broadcaster = gws.NewBroadcaster(op, msg)
	defer broadcaster.Close()
	em.Publish(topic, broadcaster)
}

Autobahn Test

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

Communication

微信需要先添加好友再拉群, 请注明来自 GitHub

WeChat      QQ

Acknowledgments

The following project had particular influence on gws's design.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrUnauthorized 未通过鉴权认证
	// Failure to pass forensic authentication
	ErrUnauthorized = errors.New("unauthorized")

	// ErrHandshake 握手错误, 请求头未通过校验
	// Handshake error, request header does not pass checksum.
	ErrHandshake = errors.New("handshake error")

	// ErrCompressionNegotiation 压缩拓展协商失败, 请尝试关闭压缩
	// Compression extension negotiation failed, please try to disable compression.
	ErrCompressionNegotiation = errors.New("invalid compression negotiation")

	// ErrSubprotocolNegotiation 子协议协商失败
	// Sub-protocol negotiation failed
	ErrSubprotocolNegotiation = errors.New("sub-protocol negotiation failed")

	// ErrTextEncoding 文本消息编码错误(必须是utf8编码)
	// Text message encoding error (must be utf8)
	ErrTextEncoding = errors.New("invalid text encoding")

	// ErrConnClosed 连接已关闭
	// Connection closed
	ErrConnClosed = net.ErrClosed

	// ErrUnsupportedProtocol 不支持的网络协议
	// Unsupported network protocols
	ErrUnsupportedProtocol = errors.New("unsupported protocol")
)

Functions

func Recovery added in v1.0.1

func Recovery(logger Logger)

Types

type Broadcaster added in v1.6.2

type Broadcaster struct {
	// contains filtered or unexported fields
}

func NewBroadcaster added in v1.6.2

func NewBroadcaster(opcode Opcode, payload []byte) *Broadcaster

NewBroadcaster 创建广播器 相比循环调用WriteAsync, Broadcaster只会压缩一次消息, 可以节省大量CPU开销. Instead of calling WriteAsync in a loop, Broadcaster compresses the message only once, saving a lot of CPU overhead.

func (*Broadcaster) Broadcast added in v1.6.2

func (c *Broadcaster) Broadcast(socket *Conn) error

Broadcast 广播 向客户端发送广播消息 Send a broadcast message to a client.

func (*Broadcaster) Close added in v1.6.12

func (c *Broadcaster) Close() error

Close 释放资源 在完成所有Broadcast调用之后执行Close方法释放资源. Call the Close method after all the Broadcasts have been completed to release the resources.

type BuiltinEventHandler added in v1.3.0

type BuiltinEventHandler struct{}

func (BuiltinEventHandler) OnClose added in v1.3.0

func (b BuiltinEventHandler) OnClose(socket *Conn, err error)

func (BuiltinEventHandler) OnMessage added in v1.3.0

func (b BuiltinEventHandler) OnMessage(socket *Conn, message *Message)

func (BuiltinEventHandler) OnOpen added in v1.3.0

func (b BuiltinEventHandler) OnOpen(socket *Conn)

func (BuiltinEventHandler) OnPing added in v1.3.0

func (b BuiltinEventHandler) OnPing(socket *Conn, payload []byte)

func (BuiltinEventHandler) OnPong added in v1.3.0

func (b BuiltinEventHandler) OnPong(socket *Conn, payload []byte)

type ClientOption added in v1.4.2

type ClientOption struct {
	// 写缓冲区的大小, v1.4.5版本此参数被废弃
	// Deprecated: Size of the write buffer, v1.4.5 version of this parameter is deprecated
	WriteBufferSize int

	PermessageDeflate   PermessageDeflate
	ParallelEnabled     bool
	ParallelGolimit     int
	ReadMaxPayloadSize  int
	ReadBufferSize      int
	WriteMaxPayloadSize int
	CheckUtf8Enabled    bool
	Logger              Logger
	Recovery            func(logger Logger)

	// 连接地址, 例如 wss://example.com/connect
	// server address, eg: wss://example.com/connect
	Addr string

	// 额外的请求头
	// extra request header
	RequestHeader http.Header

	// 握手超时时间
	HandshakeTimeout time.Duration

	// TLS设置
	TlsConfig *tls.Config

	// 拨号器
	// 默认是返回net.Dialer实例, 也可以用于设置代理.
	// The default is to return the net.Dialer instance
	// Can also be used to set a proxy, for example
	// NewDialer: func() (proxy.Dialer, error) {
	//		return proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, nil)
	// },
	NewDialer func() (Dialer, error)

	// 创建session存储空间
	// 用于自定义SessionStorage实现
	// For custom SessionStorage implementations
	NewSession func() SessionStorage
}

type CloseError added in v1.6.0

type CloseError struct {
	Code   uint16
	Reason []byte
}

func (*CloseError) Error added in v1.6.0

func (c *CloseError) Error() string

type ConcurrentMap added in v1.2.5

type ConcurrentMap[K comparable, V any] struct {
	// contains filtered or unexported fields
}

func NewConcurrentMap added in v1.2.5

func NewConcurrentMap[K comparable, V any](sharding uint64) *ConcurrentMap[K, V]

func (*ConcurrentMap[K, V]) Delete added in v1.2.5

func (c *ConcurrentMap[K, V]) Delete(key K)

func (*ConcurrentMap[K, V]) Len added in v1.2.5

func (c *ConcurrentMap[K, V]) Len() int

func (*ConcurrentMap[K, V]) Load added in v1.2.5

func (c *ConcurrentMap[K, V]) Load(key K) (value V, exist bool)

func (*ConcurrentMap[K, V]) Range added in v1.2.5

func (c *ConcurrentMap[K, V]) Range(f func(key K, value V) bool)

Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration.

func (*ConcurrentMap[K, V]) Store added in v1.2.5

func (c *ConcurrentMap[K, V]) Store(key K, value V)

type Config added in v1.2.0

type Config struct {

	// 是否开启并行消息处理
	// Whether to enable parallel message processing
	ParallelEnabled bool

	// (单个连接)用于并行消息处理的协程数量限制
	// Limit on the number of concurrent goroutine used for parallel message processing (single connection)
	ParallelGolimit int

	// 最大读取的消息内容长度
	// Maximum read message content length
	ReadMaxPayloadSize int

	// 读缓冲区的大小
	// Size of the read buffer
	ReadBufferSize int

	// 最大写入的消息内容长度
	// Maximum length of written message content
	WriteMaxPayloadSize int

	// 写缓冲区的大小, v1.4.5版本此参数被废弃
	// Deprecated: Size of the write buffer, v1.4.5 version of this parameter is deprecated
	WriteBufferSize int

	// 是否检查文本utf8编码, 关闭性能会好点
	// Whether to check the text utf8 encoding, turn off the performance will be better
	CheckUtf8Enabled bool

	// 消息回调(OnMessage)的恢复程序
	// Message callback (OnMessage) recovery program
	Recovery func(logger Logger)

	// 日志工具
	// Logging tools
	Logger Logger
	// contains filtered or unexported fields
}

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

func NewClient added in v1.4.2

func NewClient(handler Event, option *ClientOption) (*Conn, *http.Response, error)

NewClient 创建客户端 Create New client

func NewClientFromConn added in v1.5.1

func NewClientFromConn(handler Event, option *ClientOption, conn net.Conn) (*Conn, *http.Response, error)

NewClientFromConn 通过外部连接创建客户端, 支持 TCP/KCP/Unix Domain Socket Create New client via external connection, supports TCP/KCP/Unix Domain Socket.

func (*Conn) LocalAddr added in v1.0.1

func (c *Conn) LocalAddr() net.Addr

func (*Conn) NetConn added in v1.2.10

func (c *Conn) NetConn() net.Conn

NetConn get tcp/tls/kcp... connection

func (*Conn) ReadLoop added in v1.4.8

func (c *Conn) ReadLoop()

ReadLoop 循环读取消息. 如果复用了HTTP Server, 建议开启goroutine, 阻塞会导致请求上下文无法被GC. Read messages in a loop. If HTTP Server is reused, it is recommended to enable goroutine, as blocking will prevent the context from being GC.

func (*Conn) RemoteAddr added in v1.0.1

func (c *Conn) RemoteAddr() net.Addr

func (*Conn) Session added in v1.6.12

func (c *Conn) Session() SessionStorage

Session 获取会话存储 get session storage

func (*Conn) SetDeadline

func (c *Conn) SetDeadline(t time.Time) error

SetDeadline sets deadline

func (*Conn) SetNoDelay added in v1.6.2

func (c *Conn) SetNoDelay(noDelay bool) error

SetNoDelay controls whether the operating system should delay packet transmission in hopes of sending fewer packets (Nagle's algorithm). The default is true (no delay), meaning that data is sent as soon as possible after a Write.

func (*Conn) SetReadDeadline added in v1.1.2

func (c *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline sets read deadline

func (*Conn) SetWriteDeadline added in v1.1.2

func (c *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets write deadline

func (*Conn) SubProtocol added in v1.6.5

func (c *Conn) SubProtocol() string

SubProtocol 获取协商的子协议 Get negotiated sub-protocols

func (*Conn) WriteAsync added in v1.3.0

func (c *Conn) WriteAsync(opcode Opcode, payload []byte, callback func(error))

WriteAsync 异步写 异步非阻塞地将消息写入到任务队列, 收到回调后才允许回收payload内存 Asynchronously and non-blockingly write the message to the task queue, allowing the payload memory to be reclaimed only after a callback is received.

func (*Conn) WriteClose

func (c *Conn) WriteClose(code uint16, reason []byte)

WriteClose 发送关闭帧, 主动断开连接 没有特殊需求的话, 推荐code=1000, reason=nil Send shutdown frame, active disconnection If you don't have any special needs, we recommend code=1000, reason=nil https://developer.mozilla.org/zh-CN/docs/Web/API/CloseEvent#status_codes

func (*Conn) WriteMessage added in v1.1.0

func (c *Conn) WriteMessage(opcode Opcode, payload []byte) error

WriteMessage 写入文本/二进制消息, 文本消息应该使用UTF8编码 Write text/binary messages, text messages should be encoded in UTF8.

func (*Conn) WritePing

func (c *Conn) WritePing(payload []byte) error

WritePing 写入Ping消息, 携带的信息不要超过125字节 Control frame length cannot exceed 125 bytes

func (*Conn) WritePong

func (c *Conn) WritePong(payload []byte) error

WritePong 写入Pong消息, 携带的信息不要超过125字节 Control frame length cannot exceed 125 bytes

func (*Conn) WriteString added in v1.2.10

func (c *Conn) WriteString(s string) error

WriteString 写入文本消息, 使用UTF8编码. Write text messages, should be encoded in UTF8.

func (*Conn) Writev added in v1.8.0

func (c *Conn) Writev(opcode Opcode, payloads ...[]byte) error

Writev 类似WriteMessage, 区别是可以一次写入多个切片 Similar to WriteMessage, except that you can write multiple slices at once.

func (*Conn) WritevAsync added in v1.8.0

func (c *Conn) WritevAsync(opcode Opcode, payloads [][]byte, callback func(error))

WritevAsync 类似WriteAsync, 区别是可以一次写入多个切片 Similar to WriteAsync, except that you can write multiple slices at once.

type Dialer added in v1.6.0

type Dialer interface {
	Dial(network, addr string) (c net.Conn, err error)
}

type Event added in v1.1.2

type Event interface {
	// OnOpen 建立连接事件
	// WebSocket connection was successfully established
	OnOpen(socket *Conn)

	// OnClose 关闭事件
	// 接收到了网络连接另一端发送的关闭帧, 或者IO过程中出现错误主动断开连接
	// 如果是前者, err可以断言为*CloseError
	// Received a close frame from the other end of the network connection, or disconnected voluntarily due to an error in the IO process
	// In the former case, err can be asserted as *CloseError
	OnClose(socket *Conn, err error)

	// OnPing 心跳探测事件
	// Received a ping frame
	OnPing(socket *Conn, payload []byte)

	// OnPong 心跳响应事件
	// Received a pong frame
	OnPong(socket *Conn, payload []byte)

	// OnMessage 消息事件
	// 如果开启了ParallelEnabled, 会并行地调用OnMessage; 没有做recover处理.
	// If ParallelEnabled is enabled, OnMessage is called in parallel. No recover is done.
	OnMessage(socket *Conn, message *Message)
}

type Logger added in v1.6.13

type Logger interface {
	Error(v ...any)
}

type Message

type Message struct {

	// 操作码
	Opcode Opcode

	// 消息内容
	Data *bytes.Buffer
	// contains filtered or unexported fields
}

func (*Message) Bytes

func (c *Message) Bytes() []byte

func (*Message) Close

func (c *Message) Close() error

Close recycle buffer

func (*Message) Read added in v1.1.0

func (c *Message) Read(p []byte) (n int, err error)

type Opcode

type Opcode uint8
const (
	OpcodeContinuation    Opcode = 0x0
	OpcodeText            Opcode = 0x1
	OpcodeBinary          Opcode = 0x2
	OpcodeCloseConnection Opcode = 0x8
	OpcodePing            Opcode = 0x9
	OpcodePong            Opcode = 0xA
)

type PermessageDeflate added in v1.8.0

type PermessageDeflate struct {
	// 是否开启压缩
	// Whether to turn on compression
	Enabled bool

	// 压缩级别
	// Compress level
	Level int

	// 压缩阈值, 长度小于阈值的消息不会被压缩
	// Compression threshold, messages below the threshold will not be compressed
	Threshold int

	// 压缩器内存池大小
	// 数值越大竞争的概率越小, 但是会耗费大量内存
	// Compressor memory pool size
	// The higher the value the lower the probability of competition, but it will consume a lot of memory
	PoolSize int

	// 服务端上下文接管
	// Server side context takeover
	ServerContextTakeover bool

	// 客户端上下文接管
	// Client side context takeover
	ClientContextTakeover bool

	// 服务端滑动窗口指数
	// 取值范围 8<=n<=15, 表示pow(2,n)个字节
	// The server-side sliding window index
	// Range 8<=n<=15, means pow(2,n) bytes.
	ServerMaxWindowBits int

	// 客户端滑动窗口指数
	// 取值范围 8<=x<=15, 表示pow(2,n)个字节
	// The client-side sliding window index
	// Range 8<=n<=15, means pow(2,n) bytes.
	ClientMaxWindowBits int
}

PermessageDeflate 压缩拓展配置 对于gws client, 建议开启上下文接管, 不修改滑动窗口指数, 提供最好的兼容性. 对于gws server, 如果开启上下文接管, 每个连接会占用更多内存, 合理配置滑动窗口指数. For gws client, it is recommended to enable contextual takeover and not modify the sliding window index to provide the best compatibility. For gws server, if you turn on context-side takeover, each connection takes up more memory, configure the sliding window index appropriately.

type Server added in v1.4.7

type Server struct {

	// OnError
	OnError func(conn net.Conn, err error)

	// OnRequest
	OnRequest func(conn net.Conn, br *bufio.Reader, r *http.Request)
	// contains filtered or unexported fields
}

func NewServer added in v1.4.7

func NewServer(eventHandler Event, option *ServerOption) *Server

NewServer 创建websocket服务器 create a websocket server

func (*Server) GetUpgrader added in v1.8.0

func (c *Server) GetUpgrader() *Upgrader

func (*Server) Run added in v1.4.7

func (c *Server) Run(addr string) error

Run 运行. 可以被多次调用, 监听不同的地址. It can be called multiple times, listening to different addresses.

func (*Server) RunListener added in v1.4.9

func (c *Server) RunListener(listener net.Listener) error

RunListener 运行网络监听器 Running the network listener

func (*Server) RunTLS added in v1.4.7

func (c *Server) RunTLS(addr string, certFile, keyFile string) error

RunTLS 运行. 可以被多次调用, 监听不同的地址. It can be called multiple times, listening to different addresses.

type ServerOption added in v1.4.0

type ServerOption struct {

	// 写缓冲区的大小, v1.4.5版本此参数被废弃
	// Deprecated: Size of the write buffer, v1.4.5 version of this parameter is deprecated
	WriteBufferSize int

	PermessageDeflate   PermessageDeflate
	ParallelEnabled     bool
	ParallelGolimit     int
	ReadMaxPayloadSize  int
	ReadBufferSize      int
	WriteMaxPayloadSize int
	CheckUtf8Enabled    bool
	Logger              Logger
	Recovery            func(logger Logger)

	// TLS设置
	TlsConfig *tls.Config

	// 握手超时时间
	HandshakeTimeout time.Duration

	// WebSocket子协议, 握手失败会断开连接
	// WebSocket sub-protocol, handshake failure disconnects the connection
	SubProtocols []string

	// 额外的响应头(可能不受客户端支持)
	// Additional response headers (may not be supported by the client)
	// https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3
	ResponseHeader http.Header

	// 鉴权
	// Authentication of requests for connection establishment
	Authorize func(r *http.Request, session SessionStorage) bool

	// 创建session存储空间
	// 用于自定义SessionStorage实现
	// For custom SessionStorage implementations
	NewSession func() SessionStorage
	// contains filtered or unexported fields
}

type SessionStorage added in v1.2.3

type SessionStorage interface {
	Len() int
	Load(key string) (value any, exist bool)
	Delete(key string)
	Store(key string, value any)
	Range(f func(key string, value any) bool)
}

type Upgrader

type Upgrader struct {
	// contains filtered or unexported fields
}

func NewUpgrader added in v1.2.11

func NewUpgrader(eventHandler Event, option *ServerOption) *Upgrader

func (*Upgrader) Upgrade

func (c *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request) (*Conn, error)

Upgrade 升级HTTP到WebSocket协议 http upgrade to websocket protocol

func (*Upgrader) UpgradeFromConn added in v1.8.0

func (c *Upgrader) UpgradeFromConn(conn net.Conn, br *bufio.Reader, r *http.Request) (*Conn, error)

UpgradeFromConn 从连接(TCP/KCP/Unix Domain Socket...)升级到WebSocket协议 From connection (TCP/KCP/Unix Domain Socket...) Upgrade to WebSocket protocol

Directories

Path Synopsis
examples
wss

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL