Skip to content
forked from lesismal/nbio

Pure Go 1000k+ connections solution, support tls/http1.x/websocket and basically compatible with net/http, with high-performance and low memory cost, non-blocking, event-driven, easy-to-use.

License

Notifications You must be signed in to change notification settings

kingcanfish/nbio

Repository files navigation

NBIO - NON-BLOCKING IO / NIUBILITY IO

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)
  • tls supported
  • writev supported
  • least dependency

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

    // LockThread represents poller's goroutine to lock thread or not.
    LockThread 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.OnMemAlloc(func(c *Conn) []byte {
    return memPool.Get().([]byte)
})
g.OnMemFree(func(c *Conn, b []byte) {
    memPool.Put(b)
})

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

Bench Examples

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

Dependency

nbio depends on std lib only.

extension for TLS depends on lesismal/llib/std/crypto/tls, which is copied from go1.6 and rewrited, if tls is used like the example, go1.6+ is needed.

About

Pure Go 1000k+ connections solution, support tls/http1.x/websocket and basically compatible with net/http, with high-performance and low memory cost, non-blocking, event-driven, easy-to-use.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 99.5%
  • Other 0.5%