Giter VIP home page Giter VIP logo

socketio's Introduction

socketio

socket.io/engine.io implementation in Go

GoDoc Go Report Card license Build Status

Install

go get -v -u github.com/zyxar/socketio

Features

  • compatible with official nodejs implementation (w/o room);
  • socket.io server;
  • socket.io client (websocket only);
  • engine.io server;
  • engine.io client (websocket only);
  • binary data;
  • namespace support;
  • socket.io-msgpack-parser support;

Example

Server:

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/zyxar/socketio"
)

func main() {
	server, _ := socketio.NewServer(time.Second*25, time.Second*5, socketio.DefaultParser)
	server.Namespace("/").
		OnConnect(func(so socketio.Socket) {
			log.Println("connected:", so.RemoteAddr(), so.Sid(), so.Namespace())
		}).
		OnDisconnect(func(so socketio.Socket) {
			log.Printf("%v %v %q disconnected", so.Sid(), so.RemoteAddr(), so.Namespace())
		}).
		OnError(func(so socketio.Socket, err ...interface{}) {
			log.Println("socket", so.Sid(), so.RemoteAddr(), so.Namespace(), "error:", err)
		}).
		OnEvent("message", func(so socketio.Socket, data string) {
			log.Println(data)
		})

	http.ListenAndServe(":8081", server)
}

Client:

const io = require('socket.io-client');
const socket = io('http://localhost:8081');
var id;

socket.on('connect', function() {
  console.log('connected');
  if (id === undefined) {
    id = setInterval(function() {
      socket.emit('message', 'hello there!')
    }, 2000);
  }
});
socket.on('event', console.log);
socket.on('disconnect', function() {
  console.log('disconnected');
  if (id) {
    clearInterval(id);
    id = undefined;
  }
});

With Acknowledgements

  • Server -> Client

Server:

	so.Emit("ack", "foo", func(msg string) {
		log.Println(msg)
	})

Client:

  socket.on('ack', function(name, fn) {
    console.log(name);
    fn('bar');
  })
  • Client -> Server

Server:

	server.Namespace("/").OnEvent("foobar", func(data string) (string, string) {
		log.Println("foobar:", data)
		return "foo", "bar"
	})

Client:

  socket.emit('foobar', '-wow-', function (foo, bar) {
    console.log('foobar:', foo, bar);
  });

With Binary Data

Server:

	server.Namespace("/").
		OnEvent("binary", func(data interface{}, b *socketio.Bytes) {
			log.Println(data)
			bb, _ := b.MarshalBinary()
			log.Printf("%x", bb)
		}).
		OnConnect(func(so socketio.Socket) {
			go func() {
				for {
					select {
					case <-time.After(time.Second * 2):
						if err := so.Emit("event", "check it out!", time.Now()); err != nil {
							log.Println(err)
							return
						}
					}
				}
			}()
		})

Client:

  var ab = new ArrayBuffer(4);
  var a = new Uint8Array(ab);
  a.set([1,2,3,4]);

  id = setInterval(function() {
    socket.emit('binary', 'buf:', ab);
  }, 2000);

  socket.on('event', console.log);

Binary Helper for protobuf

import (
	"github.com/golang/protobuf/proto"
)

type ProtoMessage struct {
	proto.Message
}

func (p ProtoMessage) MarshalBinary() ([]byte, error) {
	return proto.Marshal(p.Message)
}

func (p *ProtoMessage) UnmarshalBinary(b []byte) error {
	return proto.Unmarshal(b, p.Message)
}

Binary Helper for MessagePack

import (
	"github.com/tinylib/msgp/msgp"
)

type MessagePack struct {
	Message interface {
		msgp.MarshalSizer
		msgp.Unmarshaler
	}
}

func (m MessagePack) MarshalBinary() ([]byte, error) {
	return m.Message.MarshalMsg(nil)
}

func (m *MessagePack) UnmarshalBinary(b []byte) error {
	_, err := m.Message.UnmarshalMsg(b)
	return err
}

Customized Namespace

Server:

	server.Namespace("/ditto").OnEvent("disguise", func(msg interface{}, b socketio.Bytes) {
		bb, _ := b.MarshalBinary()
		log.Printf("%v: %x", msg, bb)
	})

Client:

let ditto = io('http://localhost:8081/ditto');
ditto.emit('disguise', 'pidgey', new ArrayBuffer(8));

Parser

The encoder and decoder provided by socketio.DefaultParser is compatible with socket.io-parser, complying with revision 4 of socket.io-protocol.

An Event or Ack Packet with any data satisfying socketio.Binary interface (e.g. socketio.Bytes) would be encoded as BinaryEvent or BinaryAck Packet respectively.

socketio.MsgpackParser, compatible with socket.io-msgpack-parser, is an alternative custom parser.

nginx as Reverse Proxy (or TLS Terminator)

upstream socketio {
    ip_hash;
    server localhost:8080;
}

server {

    # ...

    location /socket.io/ {
        if ($request_method = OPTIONS) {
                add_header Content-Length 0;
                add_header Content-Type text/plain;
                add_header Access-Control-Allow-Origin "$http_origin" always;
                add_header Access-Control-Allow-Credentials 'true' always;
                add_header Access-Control-Allow-Methods "POST,GET,OPTIONS";
                add_header Access-Control-Allow-Headers "content-type";
                return 204;
        }
        proxy_pass http://socketio;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        add_header Access-Control-Allow-Origin "$http_origin" always;
        add_header Access-Control-Allow-Credentials 'true' always;
    }
}

socketio's People

Contributors

zyxar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

socketio's Issues

Client Namespaces do not appear to work correctly

I have the following code

err := client.Dial(
	"<URL>"
	http.Header{},
	engine.WebsocketTransport,
	socket.DefaultParser,
)
if err != nil {
	panic(err)
}

err := client.Emit("/namespace", "message", func(msg string) {
	log.Println("Client.Emit", msg)
})
if err != nil {
	panic(err)
}

Upon running the second error becomes namespace unavailable. I was wondering whether this was a bug in the code, or whether I am using the library wrong.

Thanks

Namespace not working

Hi,

I am using the example code like this:

server, _ := socketio.NewServer(time.Second*25, time.Second*5, socketio.DefaultParser)
server.Namespace("/").
        OnConnect(func(so socketio.Socket) {
            log.Println("connected:", so.RemoteAddr(), so.Sid(), so.Namespace())
        }).
        OnDisconnect(func(so socketio.Socket) {
            log.Printf("%v %v %q disconnected", so.Sid(), so.RemoteAddr(), so.Namespace())
        }).
        OnError(func(so socketio.Socket, err ...interface{}) {
            log.Println("socket", so.Sid(), so.RemoteAddr(), so.Namespace(), "error:", err)
        }).
        OnEvent("join", func(so socketio.Socket, data string) {
            log.Println(data)
        })

This works very well, but if the client request a connection like "http://localhost:8081/test", and my server side likes this

server, _ := socketio.NewServer(time.Second*25, time.Second*5, socketio.DefaultParser)
server.Namespace("/test").
    OnConnect(func(so socketio.Socket) {
        log.Println("connected:", so.RemoteAddr(), so.Sid(), so.Namespace())
    }).
    OnDisconnect(func(so socketio.Socket) {
        log.Printf("%v %v %q disconnected", so.Sid(), so.RemoteAddr(), so.Namespace())
    }).
    OnError(func(so socketio.Socket, err ...interface{}) {
        log.Println("socket", so.Sid(), so.RemoteAddr(), so.Namespace(), "error:", err)
    }).
    OnEvent("join", func(so socketio.Socket, data string) {
        log.Println(data)
    })

But it doesn't work, any suggestions? Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.