A Socket.IO backend implementation written in Go

Overview

go-socket.io

The socketio package is a simple abstraction layer for different web browser- supported transport mechanisms. It is fully compatible with the Socket.IO client (version 0.6) JavaScript-library by LearnBoost Labs. By writing custom codecs the socketio could be perhaps used with other clients, too.

It provides an easy way for developers to rapidly prototype with the most popular browser transport mechanism today:

Compatibility with Socket.IO 0.7->

Go-socket.io is currently compatible with Socket.IO 0.6 clients only.

Demo

The Paper Experiment

Crash course

The socketio package works hand-in-hand with the standard http package (by plugging itself into http.ServeMux) and hence it doesn't need a full network port for itself. It has an callback-style event handling API. The callbacks are:

  • SocketIO.OnConnect
  • SocketIO.OnDisconnect
  • SocketIO.OnMessage

Other utility-methods include:

  • SocketIO.ServeMux
  • SocketIO.Broadcast
  • SocketIO.BroadcastExcept
  • SocketIO.GetConn

Each new connection will be automatically assigned an session id and using those the clients can reconnect without losing messages: the server persists clients' pending messages (until some configurable point) if they can't be immediately delivered. All writes are by design asynchronous and can be made through Conn.Send. The server also abstracts handshaking and various keep-alive mechanisms.

Finally, the actual format on the wire is described by a separate Codec. The default bundled codecs, SIOCodec and SIOStreamingCodec are fully compatible with the LearnBoost's Socket.IO client (master and development branches).

Example: A simple chat server

package main

import (
	"http"
	"log"
	"socketio"
)

func main() {
	sio := socketio.NewSocketIO(nil)

	sio.OnConnect(func(c *socketio.Conn) {
		sio.Broadcast(struct{ announcement string }{"connected: " + c.String()})
	})

	sio.OnDisconnect(func(c *socketio.Conn) {
		sio.BroadcastExcept(c,
			struct{ announcement string }{"disconnected: " + c.String()})
	})

	sio.OnMessage(func(c *socketio.Conn, msg socketio.Message) {
		sio.BroadcastExcept(c,
			struct{ message []string }{[]string{c.String(), msg.Data()}})
	})

	mux := sio.ServeMux()
	mux.Handle("/", http.FileServer("www/", "/"))

	if err := http.ListenAndServe(":8080", mux); err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

tl;dr

You can get the code and run the bundled example by following these steps:

$ git clone git://github.com/madari/go-socket.io.git
$ cd go-socket.io
$ git submodule update --init --recursive
$ make install
$ cd example
$ make
$ ./example

License

(The MIT License)

Copyright (c) 2011 Jukka-Pekka Kekkonen <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Comments
  • Tip make go1 compatible

    Tip make go1 compatible

    Hi Jukka,

    I did the minimal changes to make your nice go-socket.io package compatible with Go 1.0.x. It compiles and all unit tests run.

    Please review the error handling around syscall.EAGAIN. I guess this needs to be reworked a little.

    The example works for me, after changing the importing socketio like this socketio "github.com/nightlyone/go-socket.io"

    I guess you wanna change this to "github.com/madari/go-socket.io" after the pull.

    Thanks for your consideration.

    Best Regards

    Ingo Oeser, aka nightlyone

    opened by nightlyone 4
  • Out of Date Protocol

    Out of Date Protocol

    Socket.IO is on 0.8.4 now; the protocol has been upgraded quite a bit. Are there any plans to upgrade this library to match? Is there anything you could use help on in bringing the project up to date? I'd love to see if I could get this working on App Engine as an alternative to the Channel API. Google's App Engine team is really interested to see what happens if it can work, too.

    opened by paddycarver 4
  • Patches justinfx

    Patches justinfx

    Done a number of things to the library:

    Memory Fixes: *There were some areas in the codecs where buffers were not being reset and memory kept growing. Changes some areas to use []byte instead of string. I still think there might be some memory leaks, but it requires more testing. I think memory will continue to grow as you pound the server with many connections sending many message. But its less a problem now that it was before

    Heartbeats:

    • Heartbeats have been split off into a separate goroutine so it doesn't become impacted by heavy message tracffic and drop users.

    Authorization:

    • Added an authorization hook into the handler so that the user can specify a function that returns bool on whether the connection is authorized, based on the request.
    opened by justinfx 3
  • connection.go: reader() - cannot send messages over 4096 bytes

    connection.go: reader() - cannot send messages over 4096 bytes

    It seems that even though you can set c.sio.config.ReadBufferSize to any size, the underlying transport buffers are still using the default 4096 buffer value? So as it stands, if you increase ReadBufferSize beyond 4096 and send a large message, you get a bufio: Buffer Full, which is unhandled and drops the connection. I have been trying to work out a temporary solution where it checks for this error, and continues to loop and build the total amount until EOF. But mainly its been a hack.

    Is this something that is going to be solved in the streaming codec with v0.7? Or can you see any clear solutions as it stands? I was able to get my hack to work in the sense of allowing an unlimited size message, but obviously that is not desirable, and the value of ReadBufferSize should really set a true limit. Maybe there needs to be a MaxMessageSize or something, so the ReadBufferSize can keep being reused to build up the total message UP TO MaxMessageSize. If it exceeds that, it would send back some kind of socketio failure, or, i guess drop the connection still.

    opened by justinfx 2
  • connection.go:327: undefined: closed

    connection.go:327: undefined: closed

    The latest Go update breaks make...

    [[email protected] go-socket.io]$ make clean rm -rf _.o *.a *.[568vq] [568vq].out *.so _obj _test _testmain.go *.exe cgo .cgo[12]. test.out build.out [[email protected] go-socket.io]$ make 6g -o go.6 util.go servemux.go message.go config.go session.go socketio.go connection.go codec.go codec_sio.go codec_siostreaming.go transport.go transport_xhrpolling.go transport_xhrmultipart.go transport_htmlfile.go transport_websocket.go transport_flashsocket.go transport_jsonppolling.go client.go doc.go connection.go:327: undefined: closed connection.go:375: undefined: closed make: *** [go.6] Error 1

    opened by jamesthornton 2
  • fixes for handling

    fixes for handling "Origin" Header

    • Header["Origin"] was returning a slice, which was directly formatted into the response Header and would fail to match the original origin. Using Header.Get("Origin") now
    opened by justinfx 1
  • Message and Codec fixes

    Message and Codec fixes

    Extracted from larger pull req The changes to the codec_*test.go files was because it passed the gotest under the release. Not sure if you were testing under a certain weekly build or not.

    opened by justinfx 1
  • Use CodeLingo to Address Further Issues

    Use CodeLingo to Address Further Issues

    Hi @madari!

    Thanks for merging the fixes from our earlier pull request. They were generated by CodeLingo which we've used to find a further 187 issues in the repo. This PR adds a set of CodeLingo Tenets which catch any new cases of the found issues in PRs to your repo.

    CodeLingo will also send follow-up PRs to fix the existing repos in the codebase. Install CodeLingo GitHub app after merging this PR. It will always be free for open source.

    We're most interested to see if we can help with project specific bugs. Tell us about more interesting issues and we'll see if our tech can help - free of charge.

    Thanks, Leila and the CodeLingo Team

    opened by CodeLingoTeam 0
  • go 1 support

    go 1 support

    on gnanderson's branch i have tried to do some a basic update but it would be great if you could update the repository name to the package name socketio https://github.com/gnanderson/go-socket.io/pull/1

    opened by dspiteself 0
  • fix for interface conversion error

    fix for interface conversion error

    trying to connect (jsonp-polling, xhr-long polliing) using https protocol throws the following error.

    panic: interface conversion: net.Conn is *tls.Conn, not *net.TCPConn [recovered] panic: runtime error: invalid memory address or nil pointer dereference

    opened by lmumar 0
  • connection.go:265 -  unable to queue heartbeat. fail now. TODO: FIXME

    connection.go:265 - unable to queue heartbeat. fail now. TODO: FIXME

    Let me just start by saying thank you so much for this library. I am learning Go right now by porting a Message Server over from python (Tornado, TornadIO, ZMQ) to Go and I'm really excited by these bindings so far!

    I'm hitting one of your Fix Me's in connection.go:265 c.sio.Log("sio/keepalive: unable to queue heartbeat. fail now. TODO: FIXME", c)

    What I am doing is rapid fire throughput tests with a command line client. When I use only a single client, I dont hit this wall. When I run 2 concurrent connections, the messaging hangs on this for a moment and ultimately then finishes, returning these errors after all the queued messages have been delivered.

    My question is mainly about what is really happening here. Does it have anything to do with the heartbeats being queued on the same channel as the messages, and they are saturating the buffer to where heartbeats cant get through? Or is it a matter of raising the queue length value? Is it a situation where ideally the heartbeat needs to be suspended while there is actual activity?

    Thanks! -- justin

    Accepted Defect 
    opened by justinfx 7
Simple Relay between a Unix socket and a TCP socket, and vice versa.

Simple TCP <-> Unix Relay simpletcpunixrelay is a program which exposes a TCP endpoint as a Unix socket and vice versa. Usecase Let's say you are runn

Antoine Catton 0 Dec 4, 2021
A Socket.IO backend implementation written in Go

go-socket.io The socketio package is a simple abstraction layer for different web browser- supported transport mechanisms. It is fully compatible with

Jukka-Pekka Kekkonen 408 Sep 25, 2022
A diffie-hellman socket implementation in golang.

I tried to implement the diffie hellman key exchange in golang with the use of sockets to understand how this protocol works and to learn golang. So its a development project: obviously don't use it in production.

AdriDevelopsThings 3 Aug 9, 2022
Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and deadline support. MIT Licensed.

socket Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and d

Matt Layher 44 Aug 3, 2022
Encode and Decode Message Length Indicators for TCP/IP socket based protocols

SimpleMLI A Message Length Indicator Encoder/Decoder Message Length Indicators (MLI) are commonly used in communications over raw TCP/IP sockets. This

American Express 23 Sep 10, 2022
Web socket in go :book:

websockets-in-go curl -i -G -d "id=UC29ju8bIPH5as8OGnQzwJyA&part=statistics&key=AIzaSyCuhMEgZHU6Epb9rjzKtRRGJY8bLEZjTA8" https://www.googleapis.com/yo

Sudip Shrestha 2 Sep 6, 2021
A TCP socket based chat server implemented using Go

Go Chat Server A better TCP socket chat server implemented using Go Connecting nc localhost 5000 Docker Build the container image docker build -t grub

Christopher Gruber 0 Oct 16, 2021
Demonstration of using Pion WebRTC with a shared socket

pion-webrtc-shared-socket This example demonstrates how Pion WebRTC can use an already listening UDP socket. On startup we listen on UDP Socket 8000.

Sean DuBois 6 Apr 4, 2022
Native macOS networking for QEMU using vmnet.framework and socket networking.

qemu-vmnet Native macOS networking for QEMU using vmnet.framework and socket networking. Getting started TODO -netdev socket,id=net0,udp=:1234,localad

Alessio Dionisi 25 Aug 1, 2022
Simple forwarding a unix domain socket to a local port.

WaziApp Proxy WaziApp proxy is a simple http proxy that is intended to listen on the WaziApp unix socket /var/lib/waziapp/proxy.sock and forwards to a

Waziup 0 Nov 18, 2021
Prometheus nginx socket exporter

stand-alone version of k8s/ingress-nginx' prometheus exporter based on openresty/lua-nginx-module how it works exporter opens socket (/tmp/prometheus-

Alex 4 Aug 8, 2022
TCP output for beats to send events over TCP socket.

beats-tcp-output How To Use Clone this project to elastic/beats/libbeat/output/ Modify elastic/beats/libbeat/publisher/includes/includes.go : // add i

ichx 2 Aug 25, 2022
Golang simple socket framework

go-socket go-socket是一个Go(golang)编写的socket服务器、客户端开发框架包,使用非常简单,里面的两个示例代码验证通过 使用方式

周建 2 Jun 15, 2022
Plugs module to see different types of plug types needed in different countries, and a comparison tool between two countries plug socket types.

plugs Importing the module: go get github.com/matthewboyd/plugs "github.com/matthewboyd/plugs" How to use the module: There are two functions wi

Matthew Boyd 2 Dec 28, 2021
Gosof - A simple and easy golang socket server/client framework

Golang Socket Framework What A simple and easy golang socket server/client framework especially convenient for handling TCP fixed-length header and va

jung hyun, ko 1 Feb 27, 2022
A Socket Framework Built Using Golang

A Socket Framework Built Using Golang

GolangDevs 4 Jan 20, 2022
Golang unix-socket wrapper

Sockunx Golang unix-socket wrapper Server Running server server, e := sockunx.NewServer("/path/to/your/socks.sock", 512) if e != nil { log.Fatal(e

Surya Dewangga 0 Jan 17, 2022
Backend implementation using go, proto3 and gRPC for a mock online store

Backend implementation using go, proto3 and gRPC for a mock online store Ricardo RICO URIBE Tasks I - Order service The current system exposes a produ

Ricardo Rico 0 Oct 10, 2021
llb - It's a very simple but quick backend for proxy servers. Can be useful for fast redirection to predefined domain with zero memory allocation and fast response.

llb What the f--k it is? It's a very simple but quick backend for proxy servers. You can setup redirect to your main domain or just show HTTP/1.1 404

Kirill Danshin 12 Jan 23, 2022