New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Websockets Broadcast outside a On() handler? #1159

Open
howesteve opened this Issue Dec 24, 2018 · 3 comments

Comments

Projects
None yet
3 participants
@howesteve
Copy link

howesteve commented Dec 24, 2018

Hello,

I can't find a way to broadcast a message using websockets outside a Connection.On() handler.

Use case: what if I need to broadcast a server status like every second to some or all clients? That wouldn't be inside a handler because the message wouldn't be inside a Connection.On() handler.

I think there should be Server.To() function as well. Or am I missing something?

Thanks,
Howe

@kataras

This comment has been minimized.

Copy link
Owner

kataras commented Dec 24, 2018

Hi,

Of course there is a To, on the chat example you can see:

// where c is the Connection inside `Server#OnConnection`
c.To(websocket.Broadcast).Emit("chat", msg)

Yours,
Makis

@howesteve

This comment has been minimized.

Copy link

howesteve commented Dec 24, 2018

Hi kataras,

Yes, I saw that, but that is my precise point: you must have a websocket.Conn (c in your example) to do that. I'll have access to the websocket.Connection after the OnConnect() event fired, right? That means, only in answering an event which is a client connect.
What if I start the server beaconing a signal from the server? That means I'll not be answering any events and so I won't be inside a OnConnect() event nor a websocket.Connection.

Right now the way I'm seeing out of this is using server.GetConnections(), which is not efficient:

package main

import (
	"fmt"
	"time"

	"github.com/kataras/iris"
	"github.com/kataras/iris/websocket"
)

func handleConnection(c websocket.Connection) {
	// Read events from browser
	c.On("time", func(msg string) {
		/// 
	})
}

func main() {
	app := iris.New()
	ws := websocket.New(websocket.Config{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	})
	app.Get("/ws", ws.Handler())
	ws.OnConnection(handleConnection)
 	// beacon
	go func() {
		for {
			time.Sleep(1 * time.Second)
			// no ws.To() method, have to use this
			conns := ws.GetConnections()
			if len(conns) > 1 {
				// not thread safe I know just for illustrating
				conns[0].To(websocket.Broadcast).Emit("time", fmt.Sprintf("Server time: %v", time.Now()))
			}
		}
	}()
	app.Run(iris.Addr(":3000"))
}

Thanks,
Howe

@dibyendu

This comment has been minimized.

Copy link
Contributor

dibyendu commented Jan 17, 2019

Yes this feature would be quite useful in view of the use case @howesteve mentioned. I also felt in need of this once but eventually worked around it by some dirty hack. In fact, the other popular web-socket wrapper library socket.io has that too. There are multiple (I found 3) ways of broadcasting/multicasting messages in socket.io:

  1. using socket.broadcast.emit, where socket is a connected client socket. This is what we currently have as c.To(websocket.Broadcast).Emit("broadcast event", "").
var io = require('socket.io')(80);
io.on('connection', function (socket) {
  socket.broadcast.emit('user connected');
});
  1. io.sockets.emit, where sockets represents a collection of all connected sockets. This is equivalent to ws.GetConnections() as mentioned by @howesteve. But we still need to check the return value of ws.GetConnections() and call the Emit function on a connected client-socket (like ws.GetConnections()[0].To(websocket.Broadcast).Emit(...)) unlike socket.io, where all these overheads are handled internally and the emit function is exposed to the server (io) space.
io.sockets.emit('hi', 'everyone');
  1. finally there is io.emit, where we don't need to rely on any connected socket at all. The server (io) silently ignores the broadcasting in case there is no client connected.
io.on('connection', function(socket){
  socket.emit('request', /* */); // emit an event to the socket
  io.emit('broadcast', /* */); // emit an event to all connected sockets
  socket.on('reply', function(){ /* */ }); // listen to the event
});

This io.emit('broadcast', 'message'); block could be placed outside the io.on('connection', function(socket){ /* */ }) callback as well.

This last feature is missing. Something similar to ws.To(Broadcast/Room/Socket).Emit(...), that can be put outside of the ws.OnConnection callback, would be really useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment