/nbio

High-performance, non-blocking, event-driven, easy-to-use, least-dependency networking framework written in Go.

Primary LanguageGoMIT LicenseMIT

NBIO - NON-BLOCKING IO

Mentioned in Awesome Go

GoDoc MIT licensed Build Status Go Report Card Coverage Statusd

Contents

Features

  • 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

Installation

  1. Get and install nbio
$ go get -u github.com/lesismal/nbio
  1. Import in your code:
import "github.com/lesismal/nbio"

Quick Start

  • 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)
// ...

API Examples

New Gopher For Server-Side

g := nbio.NewGopher(nbio.Config{
    Network: "tcp",
    Addrs:   []string{"localhost:8888"},
})

New Gopher For Client-Side

g := nbio.NewGopher(nbio.Config{})

Start Gopher

err := g.Start()
if err != nil {
    fmt.Printf("Start failed: %v\n", err)
}
defer g.Stop()

Custom Other Config For Gopher

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
}

SetDeadline/SetReadDeadline/SetWriteDeadline

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))

Bind User Session With Conn

var c *nbio.Conn = ...
var session *YourSessionType = ... 
c.SetSession(session)
var c *nbio.Conn = ...
session := c.Session().(*YourSessionType)

Writev / Batch Write

var c *nbio.Conn = ...
var data [][]byte = ...
c.Writev(data)

Handle New Connection

g.OnOpen(func(c *Conn) {
    // ...
    c.SetReadDeadline(time.Now().Add(time.Second*30))
})

Handle Disconnected

g.OnClose(func(c *Conn) {
    // clear sessions from user layer
})

Handle Data

g.OnData(func(c *Conn, data []byte) {
    // decode data
    // ...
})

Handle Memory Allocation/Free For Reading

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)
})

Handle Memory Free For Writing

g.OnWriteBufferFree(func(c *Conn, b []byte) {
    // ...
})

Handle Conn Before Read

// 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))
})

Handle Conn After Read

// 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))
})

Handle Conn Before Write

g.OnData(func(c *Conn, data []byte) {
    c.SetWriteDeadline(time.Now().Add(time.Second*5))
})

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

refer to this test, or write your own test cases: