Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

socket.io client using Go

Starting with a working socket.io example (back-end: Python/Flask, front-end: socket.io.js v2.0.3), I now try to set up a client with Go but can't even pass the handshake phase. Apologies for the long post... (At the end I have also added a Python client which does what I want to implement in Go)

(The following work):


back-end:

@socketio.on('connect', namespace='/endpoint')
def connect():
    print("Client connected with request sid "+request.sid)

@socketio.on('join', namespace='/endpoint')
def join(message):
    print("Server received from client:" +message)
    print("Client just joined room with request sid "+request.sid)
    join_room(request.sid)

front-end:

namespace = '/endpoint';
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);

var client_join_message = "This is a client";    
socket.emit('join', client_join_message);

Developer tools: I notice a few requests until the browser and the server select to use websockets and exchange frames:

http://localhost:5000/socket.io/?EIO=3&transport=polling&t=LxcgetJ
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=Lxcgetf&sid=025e105a5093467d994a891367380aa3
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=Lxcgeti&sid=025e105a5093467d994a891367380aa3
ws://localhost:5000/socket.io/?EIO=3&transport=websocket&sid=025e105a5093467d994a891367380aa3
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=Lxcgetw&sid=025e105a5093467d994a891367380aa3
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=Lxcgetx&sid=025e105a5093467d994a891367380aa3

Server logs:

"GET /socket.io/?EIO=3&transport=polling&t=LxcgetJ HTTP/1.1" 200 381 0.000322
Client connected with request sid 025e105a5093467d994a891367380aa3
"POST /socket.io/?EIO=3&transport=polling&t=Lxcgetf&sid=025e105a5093467d994a891367380aa3 HTTP/1.1" 200 219 0.000806
(6450) accepted ('127.0.0.1', 45034)
"GET /socket.io/?EIO=3&transport=polling&t=Lxcgeti&sid=025e105a5093467d994a891367380aa3 HTTP/1.1" 200 227 0.003941
"POST /socket.io/?EIO=3&transport=polling&t=Lxcgetw&sid=025e105a5093467d994a891367380aa3 HTTP/1.1" 200 219 0.001650
"GET /socket.io/?EIO=3&transport=polling&t=Lxcgetx&sid=025e105a5093467d994a891367380aa3 HTTP/1.1" 200 215 0.000235
Server received from client:This is a client
Client just joined room with request sid 025e105a5093467d994a891367380aa3


My try with Go, (doesn't work):


The code comes from this client example in github.com/graarh/golang-socketio:

package main

import (
    "github.com/graarh/golang-socketio"
    "github.com/graarh/golang-socketio/transport"
    "log"
    "runtime"
    "time"
)

func main() {

    runtime.GOMAXPROCS(runtime.NumCPU())

    c, err := gosocketio.Dial(
        gosocketio.GetUrl("127.0.0.1", 5000, false),
        transport.GetDefaultWebsocketTransport())
    if err != nil {
        log.Fatal(err)
    }

    err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) {
        log.Fatal("Disconnected")
    })
    if err != nil {
        log.Fatal(err)
    }

    err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel) {
        log.Println("Connected")
    })
    if err != nil {
        log.Fatal(err)
    }

    time.Sleep(1 * time.Second)
}

Go code output:

Connected

Server logs:

"GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 200 0 1.004291

Is there anything that I'm missing? With the Go code I don't see any sid, transport=polling... Also, there are only a few questions tagged with [go] [socket.io], which makes me think I've chosen the wrong path... I would be grateful for any thoughts, ideas on this.


@John Weldon

Your code produces the following:

Client:

$ go run gotest5.go 
2017/10/11 11:21:40 Connected
2017/10/11 11:21:40 result ""
2017/10/11 11:21:40 Done

Server:

(4380) wsgi starting up on http://127.0.0.1:5000
(4380) accepted ('127.0.0.1', 38860)
127.0.0.1 - - [11/Oct/2017 11:21:40] "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1" 200 0 0.003100

Notice that the server functions on.('connect'...) and on.('join',...) didn't produce logs.


Python client (it works):

from socketIO_client import SocketIO, BaseNamespace

class ThisNamespace(BaseNamespace):
    def on_connect(self):
        print('[Connected]')
    def on_reconnect(self):
        print('[Reconnected]')
    def on_disconnect(self):
        print('[Disconnected]')

with SocketIO('127.0.0.1', 5000, ThisNamespace) as socketIO:
    this_namespace = socketIO.define(ThisNamespace, '/endpoint')

client logs:

python3 test.py 
[Connected]
[Disconnected]
[Disconnected]

server logs:

(6047) wsgi starting up on http://127.0.0.1:5000
(6047) accepted ('127.0.0.1', 38900)
127.0.0.1 - - [11/Oct/2017 11:53:27] "GET /socket.io/?t=1507712007314-0&transport=polling&EIO=3 HTTP/1.1" 200 381 0.000859
(6047) accepted ('127.0.0.1', 38902)
Client connected with request sid 919ed69264dd4e9f93e7af0294970dbd
Client disconnected with request.sid 919ed69264dd4e9f93e7af0294970dbd
127.0.0.1 - - [11/Oct/2017 11:53:27] "GET /socket.io/?sid=919ed69264dd4e9f93e7af0294970dbd&transport=websocket&EIO=3 HTTP/1.1" 200 0 0.032171
like image 587
tgogos Avatar asked Oct 04 '17 09:10

tgogos


1 Answers

I think you're doing it right except you forgot to actually send the join message, maybe something like:

package main

import (
        "log"
        "runtime"
        "sync"
        "time"

        "github.com/graarh/golang-socketio"
        "github.com/graarh/golang-socketio/transport"
)

func doSomethingWith(c *gosocketio.Client, wg *sync.WaitGroup) {
        if res, err := c.Ack("join", "This is a client", time.Second*3); err != nil {
                log.Printf("error: %v", err)
        } else {
                log.Printf("result %q", res)
        }
        wg.Done()
}

func main() {

        runtime.GOMAXPROCS(runtime.NumCPU())

        c, err := gosocketio.Dial(
                gosocketio.GetUrl("127.0.0.1", 3003, false),
                transport.GetDefaultWebsocketTransport())
        if err != nil {
                log.Fatal(err)
        }

        err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) {
                log.Fatal("Disconnected")
        })
        if err != nil {
                log.Fatal(err)
        }

        err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel) {
                log.Println("Connected")
        })
        if err != nil {
                log.Fatal(err)
        }

        wg := &sync.WaitGroup{}
        wg.Add(1)
        go doSomethingWith(c, wg)
        wg.Wait()
        log.Printf("Done")
}

Notice the goroutine call to the function that actually communicates the 'join' message to the server.

Also, notice the use of a sync.WaitGroup to block until the goroutine completes, instead of using time.Sleep() to wait.

like image 189
John Weldon Avatar answered Oct 01 '22 03:10

John Weldon