You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
package main
import (
"log""github.com/marcomoesman/fastwire"
)
funcmain() {
// Server with LZ4 compression.srvConfig:=fastwire.DefaultServerConfig()
srvConfig.Compression= fastwire.CompressionConfig{
Algorithm: fastwire.CompressionLZ4,
Hurdle: 128, // only compress payloads >= 128 bytes
}
srv, err:=fastwire.NewServer(":7777", srvConfig, &fastwire.BaseHandler{})
iferr!=nil {
log.Fatal(err)
}
srv.Start()
defersrv.Stop()
// Client must request the same compression algorithm.cliConfig:=fastwire.DefaultClientConfig()
cliConfig.Compression= fastwire.CompressionConfig{
Algorithm: fastwire.CompressionLZ4,
Hurdle: 128,
}
cli, err:=fastwire.NewClient(cliConfig, &fastwire.BaseHandler{})
iferr!=nil {
log.Fatal(err)
}
iferr:=cli.Connect("127.0.0.1:7777"); err!=nil {
log.Fatal(err)
}
defercli.Close()
}
SendImmediate for Low-Latency Messages
// SendImmediate bypasses the tick queue and sends the message immediately.// Use it for time-critical messages where the next tick is too slow.conn.SendImmediate([]byte("fire!"), 0)
// Regular Send queues for the next tick (batched with other messages).conn.Send([]byte("chat: hello"), 0)
package main
import (
"fmt""github.com/marcomoesman/fastwire"
)
funcmain() {
// Both sides must use the same dictionary for zstd.dict:= []byte("repeated game state patterns go here...")
hash:=fastwire.DictionaryHash(dict)
fmt.Printf("Dictionary SHA-256: %x\n", hash)
// During the handshake, FastWire compares dictionary hashes// to ensure both sides are using the same dictionary.// A mismatch is reported via the compression ack.
}
Choosing a Congestion Control Mode
package main
import (
"fmt""github.com/marcomoesman/fastwire"
)
funcmain() {
// Conservative (AIMD) — standard TCP-like congestion window.// Good for general-purpose or bandwidth-constrained links.conservative:=fastwire.CongestionConservativefmt.Printf("Conservative mode: %d\n", conservative)
// Aggressive — no window gating, fast retransmit.// Ideal for real-time games where latency > bandwidth fairness.aggressive:=fastwire.CongestionAggressivefmt.Printf("Aggressive mode: %d\n", aggressive)
// The default initial congestion window is 4 packets.fmt.Printf("Default initial cwnd: %d\n", fastwire.DefaultInitialCwnd)
}
Zstd Dictionary Compression
package main
import (
"fmt""log""os""github.com/marcomoesman/fastwire"
)
funcmain() {
// Load the pre-trained dictionary (same file on both client and server).dict, err:=os.ReadFile("game_state.dict")
iferr!=nil {
log.Fatal(err)
}
fmt.Printf("Dictionary loaded: %d bytes, hash: %x\n",
len(dict), fastwire.DictionaryHash(dict))
// Server config with zstd + dictionary.srvConfig:=fastwire.DefaultServerConfig()
srvConfig.Compression= fastwire.CompressionConfig{
Algorithm: fastwire.CompressionZstd,
Hurdle: 64, // compress payloads >= 64 bytesDictionary: dict,
}
srv, err:=fastwire.NewServer(":7777", srvConfig, &fastwire.BaseHandler{})
iferr!=nil {
log.Fatal(err)
}
srv.Start()
defersrv.Stop()
// Client config — must use the same dictionary.cliConfig:=fastwire.DefaultClientConfig()
cliConfig.Compression= fastwire.CompressionConfig{
Algorithm: fastwire.CompressionZstd,
Hurdle: 64,
Dictionary: dict,
}
cli, err:=fastwire.NewClient(cliConfig, &fastwire.BaseHandler{})
iferr!=nil {
log.Fatal(err)
}
iferr:=cli.Connect("127.0.0.1:7777"); err!=nil {
log.Fatal(err)
}
defercli.Close()
// Dictionary hashes are compared during the handshake.// If they match, zstd uses the dictionary for better compression// of small, repetitive payloads like game state updates.fmt.Println("Connected with zstd dictionary compression")
}
Setting the Application Protocol Version
package main
import (
"fmt""github.com/marcomoesman/fastwire"
)
funcmain() {
// Set your game's protocol version before creating server/clientfastwire.ApplicationVersion=3fmt.Printf("FastWire protocol: v%d\n", fastwire.ProtocolVersion)
fmt.Printf("Application protocol: v%d\n", fastwire.ApplicationVersion)
}
Send Batching
// Enable send batching on both server and client.srvConfig:=fastwire.DefaultServerConfig()
srvConfig.SendBatching=truecliConfig:=fastwire.DefaultClientConfig()
cliConfig.SendBatching=true// Usage is transparent — Send() and SendImmediate() work the same way.// The tick loop automatically packs small messages into fewer UDP datagrams.conn.Send([]byte("small msg 1"), 0)
conn.Send([]byte("small msg 2"), 0)
// Both messages may be packed into a single UDP datagram on the next tick.
Connection Migration
// Enable connection migration to survive IP/port changes.srvConfig:=fastwire.DefaultServerConfig()
srvConfig.ConnectionMigration=truecliConfig:=fastwire.DefaultClientConfig()
cliConfig.ConnectionMigration=true// After connecting, the migration token is automatically managed.// If the client's address changes (e.g., Wi-Fi → cellular), the// server detects the token in incoming packets and migrates the connection.
I/O Coalescing (Server)
// Enable multi-goroutine reads and async writes for high-throughput servers.config:=fastwire.DefaultServerConfig()
config.CoalesceIO=trueconfig.CoalesceReaders=8// 8 concurrent read goroutines