gosocketio

package module
v0.0.0-...-a6e1393 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 24, 2020 License: GPL-3.0, MIT Imports: 15 Imported by: 0

README

golang socket.io

golang implementation of socket.io library, client and server

You can check working chat server, based on caller library, at http://funstream.tv

Examples directory contains simple client and server.

Installation
go get github.com/VerticalOps/golang-socketio
Simple server usage
	//create
	server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())

	//handle connected
	server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
		log.Println("New client connected")
		//join them to room
		c.Join("chat")
	})

	type Message struct {
		Name string `json:"name"`
		Message string `json:"message"`
	}

	//handle custom event
	server.On("send", func(c *gosocketio.Channel, msg Message) string {
		//send event to all in room
		c.BroadcastTo("chat", "message", msg)
		return "OK"
	})

	//setup http server
	serveMux := http.NewServeMux()
	serveMux.Handle("/socket.io/", server)
	log.Panic(http.ListenAndServe(":80", serveMux))
Javascript client for caller server
var socket = io('ws://yourdomain.com', {transports: ['websocket']});

    // listen for messages
    socket.on('message', function(message) {

        console.log('new message');
        console.log(message);
    });

    socket.on('connect', function () {

        console.log('socket connected');

        //send something
        socket.emit('send', {name: "my name", message: "hello"}, function(result) {

            console.log('sended successfully');
            console.log(result);
        });
    });
Server, detailed usage
    //create server instance, you can setup transport parameters or get the default one
    //look at websocket.go for parameters description
	server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())

	// --- caller is default handlers

	//on connection handler, occurs once for each connected client
	server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) {
	    //client id is unique
		log.Println("New client connected, client id is ", c.Id())

		//you can join clients to rooms
		c.Join("room name")

		//of course, you can list the clients in the room, or account them
		channels := c.List(data.Channel)
		//or check the amount of clients in room
		amount := c.Amount(data.Channel)
		log.Println(amount, "clients in room")
	})
	//on disconnection handler, if client hangs connection unexpectedly, it will still occurs
	//you can omit function args if you do not need them
	//you can return string value for ack, or return nothing for emit
	server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
		//caller is not necessary, client will be removed from rooms
		//automatically on disconnect
		//but you can remove client from room whenever you need to
		c.Leave("room name")

		log.Println("Disconnected")
	})
	//error catching handler
	server.On(gosocketio.OnError, func(c *gosocketio.Channel) {
		log.Println("Error occurs")
	})

	// --- caller is custom handler

	//custom event handler
	server.On("handle something", func(c *gosocketio.Channel, channel Channel) string {
		log.Println("Something successfully handled")

		//you can return result of handler, in caller case
		//handler will be converted from "emit" to "ack"
		return "result"
	})

    //you can get client connection by it's id
    channel, _ := server.GetChannel("client id here")
    //and send the event to the client
    type MyEventData struct {
        Data: string
    }
    channel.Emit("my event", MyEventData{"my data"})

    //or you can send ack to client and get result back
    result, err := channel.Ack("my custom ack", MyEventData{"ack data"}, time.Second * 5)

    //you can broadcast to all clients
    server.BroadcastToAll("my event", MyEventData{"broadcast"})

    //or for clients joined to room
    server.BroadcastTo("my room", "my event", MyEventData{"room broadcast"})

    //setup http server like caller for handling connections
	serveMux := http.NewServeMux()
	serveMux.Handle("/socket.io/", server)
	log.Panic(http.ListenAndServe(":80", serveMux))
Client
    //connect to server, you can use your own transport settings
	c, err := gosocketio.Dial(
		gosocketio.GetUrl("localhost", 80, false),
		transport.GetDefaultWebsocketTransport(),
	)

	//do something, handlers and functions are same as server ones

	//close connection
	c.Close()
Roadmap
  1. Tests
  2. Travis CI
  3. http longpoll transport
  4. pure http (short-timed queries) transport
  5. binary format
Licence

Double licensed under GPL3 and MIT so you can use whichever you please.

Documentation

Index

Constants

View Source
const (
	OnConnection    = "connection"
	OnDisconnection = "disconnection"
)
View Source
const (
	HeaderForward = "X-Forwarded-For"
)

Variables

View Source
var (
	ErrorCallerNotFunc     = errors.New("f is not function")
	ErrorCallerNot2Args    = errors.New("f should have 1 or 2 args")
	ErrorCallerMaxOneValue = errors.New("f should return not more than one value")
)
View Source
var (
	//QueueBufferSize is the global buffer size for all internal channels and messages.
	//It should only be changed before using anything from this package and cannot be changed concurrently.
	QueueBufferSize = 50

	ErrorWrongHeader = errors.New("Wrong header")
)
View Source
var (
	ErrorSendTimeout     = errors.New("Timeout")
	ErrorSocketOverflood = errors.New("Socket overflood")
)
View Source
var (
	ErrorServerNotSet       = errors.New("Server not set")
	ErrorConnectionNotFound = errors.New("Connection not found")

	ErrRateLimiting = errors.New("gosocketio: Rate limiting reached, a message was dropped")
)
View Source
var (
	ErrorWaiterNotFound = errors.New("Waiter not found")
)

Functions

func GetUrl

func GetUrl(host string, port int, secure bool) string

* Get ws/wss url by host and port

Types

type Channel

type Channel struct {
	// contains filtered or unexported fields
}

* socket.io connection handler

use IsAlive to check that handler is still working use Dial to connect to websocket use In and Out channels for message exchange Close message means channel is closed ping is automatic

func (*Channel) Ack

func (c *Channel) Ack(method string, args interface{}, timeout time.Duration) (string, error)

* Create ack packet based on given data and send it and receive response

func (*Channel) Amount

func (c *Channel) Amount(room string) int

* Get amount of channels, joined to given room, using channel

func (*Channel) BroadcastTo

func (c *Channel) BroadcastTo(room, method string, args interface{})

func (*Channel) Close

func (c *Channel) Close()

* Close current channel

func (*Channel) Emit

func (c *Channel) Emit(method string, args interface{}) error

* Create packet based on given data and send it

func (*Channel) Id

func (c *Channel) Id() string

* Get id of current socket connection

func (*Channel) Ip

func (c *Channel) Ip() string

* Get ip of socket client

func (*Channel) IsAlive

func (c *Channel) IsAlive() (alive bool)

* Checks that Channel is still alive

func (*Channel) Join

func (c *Channel) Join(room string) error

* Join this channel to given room

func (*Channel) Leave

func (c *Channel) Leave(room string) error

* Remove this channel from given room

func (*Channel) List

func (c *Channel) List(room string) []*Channel

* Get list of channels, joined to given room, using channel

func (*Channel) RequestHeader

func (c *Channel) RequestHeader() http.Header

* Get request header of this connection

type Client

type Client struct {
	Channel
	// contains filtered or unexported fields
}

* Socket.io client representation

func Dial

func Dial(url string, tr transport.Transport) (*Client, error)

* connect to host and initialise socket.io protocol

The correct ws protocol url example: ws://myserver.com/socket.io/?EIO=3&transport=websocket

You can use GetUrlByHost for generating correct url

func (*Client) Close

func (c *Client) Close()

* Close client connection

func (*Client) On

func (m *Client) On(method string, f interface{}) error

* Add message processing function, and bind it to given method

type ErrorHandler

type ErrorHandler func(error)

ErrorHandler is called when an internal error occurs that cannot otherwise be returned to the caller.

type Header struct {
	Sid          string   `json:"sid"`
	Upgrades     []string `json:"upgrades"`
	PingInterval int      `json:"pingInterval"`
	PingTimeout  int      `json:"pingTimeout"`
}

* engine.io header to send or receive

type RecoveryHandler

type RecoveryHandler func(*Channel, interface{})

RecoveryHandler is called when one or more interally spawned goroutines panic, this includes goroutines that service user code. The passed interface is guaranteed to be non-nil, however the handler should check if the channel is. If the channel is non-nil the handler may use it to communicate a problem. RecoveryHandler must be safe to call concurrently.

type Server

type Server struct {
	http.Handler
	// contains filtered or unexported fields
}

* socket.io server instance

func NewServer

func NewServer(tr transport.Transport, opts ...ServerOption) *Server

* Create new socket.io server

func (*Server) Amount

func (s *Server) Amount(room string) int

* Get amount of channels, joined to given room, using server

func (*Server) AmountOfRooms

func (s *Server) AmountOfRooms() int64

* Get amount of rooms with at least one channel(or sid) joined

func (*Server) AmountOfSids

func (s *Server) AmountOfSids() int64

* Get amount of current connected sids

func (*Server) BroadcastTo

func (s *Server) BroadcastTo(room, method string, args interface{})

* Broadcast message to all room channels

func (*Server) BroadcastToAll

func (s *Server) BroadcastToAll(method string, args interface{})

* Broadcast to all clients

func (*Server) GetChannel

func (s *Server) GetChannel(sid string) (*Channel, error)

* Get channel by it's sid

func (*Server) List

func (s *Server) List(room string) []*Channel

* Get list of channels, joined to given room, using server

func (*Server) NumGoroutine

func (s *Server) NumGoroutine() int64

NumGoroutine returns the number of goroutines spawned by the server or its Channels.

func (*Server) On

func (m *Server) On(method string, f interface{}) error

* Add message processing function, and bind it to given method

func (*Server) SendOpenSequence

func (s *Server) SendOpenSequence(c *Channel) error

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

* implements ServeHTTP function from http.Handler

func (*Server) SetupEventLoop

func (s *Server) SetupEventLoop(conn transport.Connection, remoteAddr string,
	requestHeader http.Header)

* Setup event loop for given connection

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown will shutdown the server gracefully by telling all interally spawned goroutines to exit. It does not force goroutines spawned by callbacks to exit. Shutdown is not safe to call concurrently. Shutdown may be called more than once from the same goroutine as it will only error if the passed context is finished before shutdown is complete.

type ServerOption

type ServerOption func(*Server)

ServerOption is a functional server option returned by various functions in this package.

func WithErrorHandler

func WithErrorHandler(eh ErrorHandler) ServerOption

WithErrorHandler sets the given ErrorHandler in the returned ServerOption. If eh is nil the returned ServerOption does nothing.

func WithRateLimiter

func WithRateLimiter(limit int) ServerOption

WithRateLimiter returns a ServerOption that limits the number of messages concurrently handled per Channel. It does not limit the number of Channels or Websocket connections, connections may be limited via the underlying net.Listener used in the http.Server, or shadowing the Server's ServeHTTP method to limit how many requests become websockets. If limit is below 0, an unlimited number of goroutines will be allowed to spawn in response to socketio messages. If the limit is 0 then the socketio input loop will work on each function itself, this is only recommended if the user wants to control how goroutines are spawned in their on callbacks or if their callbacks are fast and don't block long. Any limit greater than 0 means 'limit' goroutines are allowed to run concurrently to service user code. If the limit is reached an incoming message will be dropped and the Servers ErrorHandler will be called, if it has one, with ErrRateLimiting. Once a goroutine servicing user code is done the limit will reduce allowing more to be run.

func WithRecoveryHandler

func WithRecoveryHandler(rh RecoveryHandler) ServerOption

WithRecoveryHandler sets the given RecoveryHandler in the returned ServerOption. If rh is nil the returned ServerOption does nothing.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL