WebSocket
A dedicated fast path โ an upgraded connection carries zero HTTP overhead, and an HTTP-only server never even probes for one. Binary and text frames, ping/pong, fragmentation, and graceful close are all implemented per RFC 6455.
hub := app.WebSocket("/ws", &breeze.WSHandlerFunc{
Connect: func(c *breeze.WSConn) { c.SendText("welcome!") },
Message: func(c *breeze.WSConn, op byte, payload []byte) {
hub.BroadcastExcept(op, payload, c) // fan out to everyone else
},
}) Ordering guarantee
A connection's messages reach its handler in the order the peer sent
them, one at a time. Delivery is per-connection FIFO, so a handler parsing
a stream can rely on it; two different connections are still handled
concurrently. OnClose runs after every message already delivered, so
per-connection state torn down there cannot be used afterwards.
WSConn
| Method | Purpose |
|---|---|
Send(opcode byte, payload []byte) error | raw frame send |
SendText(msg string) error | text frame |
SendBinary(msg []byte) error | binary frame |
Close(code uint16, reason string) | graceful close |
RemoteAddr() string | peer address |
WSHub
Every mount gets a hub for fan-out:
hub.Broadcast(opcode, payload)
hub.BroadcastText(msg)
hub.BroadcastBinary(msg)
hub.BroadcastExcept(opcode, payload, skip) // everyone but one connection
hub.Count() // live connection count Dialing out: DialWS
DialWS is the symmetric other half: a Breeze process connecting to a
WebSocket server rather than accepting one. It returns the same *WSConn type, so a peer table can hold one type for connections it accepted and
connections it dialled โ useful for peer-to-peer topologies.
conn, err := breeze.DialWS("ws://peer:9000/p2p", breeze.WSClientConfig{
HandshakeTimeout: 5 * time.Second,
Header: map[string]string{"Authorization": "Bearer " + token},
})
if err != nil {
return err
}
conn.OnMessage(func(op byte, payload []byte) { peer.handle(op, payload) })
conn.OnClose(func(code uint16, reason string) { peers.drop(conn) })
conn.SendBinary(hello) Full client handshake with Sec-WebSocket-Accept verification, mandatory
frame masking (client frames must be masked per RFC 6455), wss:// via crypto/tls, and Ping/Pong for liveness. One goroutine per dialled
connection โ sized for tens to low hundreds of peers, not tens of thousands. Reconnection is deliberately yours: OnClose is where a redial goes.
conn.Ping(payload)
conn.Pong(payload)
conn.Subprotocol() // negotiated subprotocol, if any
conn.IsClient() // true for a dialled connection Shutdown behaviour
On app.Stop(ctx), every WebSocket connection receives a Close frame with 1001 going away, and its handler's OnClose runs through the
connection's ordered queue before the listener finally closes. See Getting Started โ Graceful shutdown.