- NBIO - NON-BLOCKING IO
- Contents
- Features
- Installation
- Quick Start
- API Examples
- New Gopher For Server-Side
- New Gopher For Client-Side
- Start Gopher
- Custom Other Config For Gopher
- SetDeadline/SetReadDeadline/SetWriteDeadline
- Bind User Session With Conn
- Writev / Batch Write
- Handle New Connection
- Handle Disconnected
- Handle Data
- Handle Memory Allocation/Free For Reading
- Handle Memory Free For Writing
- Handle Conn Before Read
- Handle Conn After Read
- Handle Conn Before Write
- Std Net Examples
- Echo Examples
- TLS Examples
- HTTP Examples
- HTTPS Examples
- HTTP 1M Connections Examples
- Websocket Examples
- Websocket TLS Examples
- Websocket 1M Connections Examples
- Bench Examples
- linux: epoll
- macos(bsd): kqueue
- windows: golang std net
- nbio.Conn implements a non-blocking net.Conn(except windows)
- writev supported
- least dependency
- TLS supported
- HTTP/HTTPS 1.x
- Websocket
- HTTP 2.0
- Get and install nbio
$ go get -u github.com/lesismal/nbio
- Import in your code:
import "github.com/lesismal/nbio"
- start a server
import "github.com/lesismal/nbio"
g := nbio.NewGopher(nbio.Config{
Network: "tcp",
Addrs: []string{"localhost:8888"},
})
// echo
g.OnData(func(c *nbio.Conn, data []byte) {
c.Write(append([]byte{}, data...))
})
err := g.Start()
if err != nil {
panic(err)
}
// ...
- start a client
import "github.com/lesismal/nbio"
g := nbio.NewGopher(nbio.Config{})
g.OnData(func(c *nbio.Conn, data []byte) {
// ...
})
err := g.Start()
if err != nil {
fmt.Printf("Start failed: %v\n", err)
}
defer g.Stop()
c, err := nbio.Dial("tcp", addr)
if err != nil {
fmt.Printf("Dial failed: %v\n", err)
}
g.AddConn(c)
buf := make([]byte, 1024)
c.Write(buf)
// ...
g := nbio.NewGopher(nbio.Config{
Network: "tcp",
Addrs: []string{"localhost:8888"},
})
g := nbio.NewGopher(nbio.Config{})
err := g.Start()
if err != nil {
fmt.Printf("Start failed: %v\n", err)
}
defer g.Stop()
conf := nbio.Config struct {
// Name describes your gopher name for logging, it's set to "NB" by default
Name: "NB",
// MaxLoad represents the max online num, it's set to 10k by default
MaxLoad: 1024 * 10,
// NListener represents the listener goroutine num on *nix, it's set to 1 by default
NListener: 1,
// NPoller represents poller goroutine num, it's set to runtime.NumCPU() by default
NPoller: runtime.NumCPU(),
// ReadBufferSize represents buffer size for reading, it's set to 16k by default
ReadBufferSize: 1024 * 16,
// MaxWriteBufferSize represents max write buffer size for Conn, it's set to 1m by default.
// if the connection's Send-Q is full and the data cached by nbio is
// more than MaxWriteBufferSize, the connection would be closed by nbio.
MaxWriteBufferSize uint32
// LockListener represents listener's goroutine to lock thread or not, it's set to false by default.
LockListener bool
// LockPoller represents poller's goroutine to lock thread or not.
LockPoller bool
}
var c *nbio.Conn = ...
c.SetDeadline(time.Now().Add(time.Second * 10))
c.SetReadDeadline(time.Now().Add(time.Second * 10))
c.SetWriteDeadline(time.Now().Add(time.Second * 10))
var c *nbio.Conn = ...
var session *YourSessionType = ...
c.SetSession(session)
var c *nbio.Conn = ...
session := c.Session().(*YourSessionType)
var c *nbio.Conn = ...
var data [][]byte = ...
c.Writev(data)
g.OnOpen(func(c *Conn) {
// ...
c.SetReadDeadline(time.Now().Add(time.Second*30))
})
g.OnClose(func(c *Conn) {
// clear sessions from user layer
})
g.OnData(func(c *Conn, data []byte) {
// decode data
// ...
})
import "sync"
var memPool = sync.Pool{
New: func() interface{} {
return make([]byte, yourSize)
},
}
g.OnReadBufferAlloc(func(c *Conn) []byte {
return memPool.Get().([]byte)
})
g.OnReadBufferFree(func(c *Conn, b []byte) {
memPool.Put(b)
})
g.OnWriteBufferFree(func(c *Conn, b []byte) {
// ...
})
// BeforeRead registers callback before syscall.Read
// the handler would be called only on windows
g.OnData(func(c *Conn, data []byte) {
c.SetReadDeadline(time.Now().Add(time.Second*30))
})
// AfterRead registers callback after syscall.Read
// the handler would be called only on *nix
g.BeforeRead(func(c *Conn) {
c.SetReadDeadline(time.Now().Add(time.Second*30))
})
g.OnData(func(c *Conn, data []byte) {
c.SetWriteDeadline(time.Now().Add(time.Second*5))
})
refer to this test, or write your own test cases: