send JSON data to Unity from Node.js - node.js

I asked this question on the official forum but I guess I don't have enough rep there to be taken seriously :O
I'm using Unity3D free.
Has anyone used https://www.assetstore.unity3d.com/en/#!/content/21721 with success? This plugin actually came the closest to working (I also tried this and this but they don't work for me).
I contacted the author but haven't got a reply yet, so was wondering if someone had made this work?
(edit: I would like to point out that I don't mind buying some other plugin if you have used it and found it easy/useful to communicate with your Node.js server via SocketIO - so please recommend)
Concretely, here's my problem with it:
I cant find a way to send JSON data to Unity from Node.js as it keeps getting an error.
I tried numerous ways, and this is one of them:
io.on('connection', function(socket){
console.log('a user connected');
var data ='{"email":"some#email.com","pass":"1234"}';
var dataJson = JSON.stringify(data);
console.dir(dataJson);
socket.emit('newResults', dataJson);
console.log('server emited newResults');
socket.on('fromClient', function(data){
console.log("got msg from client");
console.dir(data);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
In Unity3D I use the following function to intercept this:
public void HandleNewResults(SocketIOEvent e){
Debug.Log(string.Format("[name: {0}, data: {1}]", e.name, e.data));
Debug.Log (new JSONObject (e.data));
}
but it crashes (it catches the error signal) at this point with (when debugging is turned on) this message:
SocketComm:TestError(SocketIOEvent) (at Assets/_Scripts/SocketComm.cs:58)
SocketIO.SocketIOComponent:EmitEvent(SocketIOEvent) (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:400)
SocketIO.SocketIOComponent:EmitEvent(String) (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:392)
SocketIO.SocketIOComponent:OnError(Object, ErrorEventArgs) (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:382)
WebSocketSharp.Ext:Emit(EventHandler`1, Object, ErrorEventArgs) (at Assets/SocketIO/WebsocketSharp/Ext.cs:992)
WebSocketSharp.WebSocket:error(String) (at Assets/SocketIO/WebsocketSharp/WebSocket.cs:1011)
WebSocketSharp.WebSocket:Send(String) (at Assets/SocketIO/WebsocketSharp/WebSocket.cs:1912)
SocketIO.SocketIOComponent:EmitPacket(Packet) (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:309)
SocketIO.SocketIOComponent:EmitClose() (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:299)
SocketIO.SocketIOComponent:Close() (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:184)
SocketIO.SocketIOComponent:OnApplicationQuit() (at Assets/SocketIO/Scripts/SocketIO/SocketIOComponent.cs:164)
Can you please shed some light on how to aproach this problem?

I'm using Unity3D free.
But SocketIO needs Unity Pro. If you want to use native .NET sockets.
Unity Pro is required in order to build using .NET sockets. You may
use a replacement package if you don't want to use native sockets.
You can use Good ol' Sockets.It's usable for sockets.

I used such code:
socket.emit('event_name', {"email":"some#email.com","pass":"1234"});
I do not know if it right. The function in unity is:
public void TestBoop (SocketIOEvent e)
{
Debug.Log ("[SocketIO] Boop received: " + e.name + "--" + e.data);
);
}
And output is:
[SocketIO] Boop received: boop--{"email":"some#email.com","pass":"1234"}
Perhaps it does't right at all but the result at least comes to unity

Make these changes:
io.on('connection', function(socket){
console.log('a user connected');
var data ='{"email":"some#email.com","pass":"1234"}';
var dataJson = JSON.stringify(data);
console.dir(dataJson);
console.log('server emited newResults');
socket.on('beep', function(){
socket.emit('boop', {'boop': dataJson});
console.log("got msg from client");
console.dir(data);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
this is will work.

Related

Why is received websocket data coming out as a buffer?

I'm trying to do a very basic websocket, but i dont understand why I'm not getting a string back.
I'm using the ws module from npm for the server. https://github.com/websockets/ws
client:
let socket = new WebSocket('wss://upload.lospec.com');
socket.addEventListener('open', function (event) {
socket.send('test');
});
server:
const wss = new WebSocket.Server({ server });
wss.on("connection", function (ws) {
ws.on("message", function (asdfasdf) {
console.log("got new id from client",asdfasdf);
});
server result:
got new id from client <Buffer 74 65 73 74>
Trying to follow the examples on the docs, as well as this tutorial: https://ably.com/blog/web-app-websockets-nodejs
But it's not coming out like a string like both places promise.
Why isn't this coming out as a string?
You probably use a different version of ws than the tutorial does. It seems like the tutorial uses a version older than v8, while you use a version of v8+.
From the changelog for 8.0.0:
Text messages and close reasons are no longer decoded to strings. They are passed as Buffers to the listeners of their respective events.
The listeners of the 'message' event now take a boolean argument specifying whether or not the message is binary (e173423).
Existing code can be migrated by decoding the buffer explicitly.
websocket.on('message', function message(data, isBinary) {
const message = isBinary ? data : data.toString();
// Continue as before.
});
websocket.on('close', function close(code, data) {
const reason = data.toString();
// Continue as before.
});
This also describes the solution.
Alternatively, you can downgrade to version 7.5.0 of ws to be on par with what the tutorial uses:
npm i ws#7.5.0
In regards to the example "sending and receiving text data" in the library docs: I believe it's an oversight on their end that this example wasn't updated when v8 was released. You could open an issue on GitHub to let them know.
If you use console.log(` ${data} `), it will not show <Buffer.
where as if you console.log(data), it will show <Buffer
e.g.
ws.on('message',data=>{
console.log(`user sended:${data}`)
})
It's a bug or normal you can say.
alter method:
ws.on('message',data=>{
data=data.toString()
console.log("user sended:",data)
})
OR
ws.on('message',data=>{
console.log("user sended:",data.toString())
})
In Latest version one need to provide %s while printing the received message. Here is the simple code snippet from official page npm websocket official page.
ws.on('message', function message(data) {
console.log('received: %s', data);
});
I was having same issue. I found the issue was because of version of ws.
So, I installed another version of ws.
Try this instead:
npm i ws#7.5.0
It worked in my case.

remoteDisconnect socket.io and redis

I'm trying to implement socket.io with Redis adapter in NodeJs.
Mostly it works, but sometimes I am still getting errors when trying to disconnect / connect sockets, so I think I haven't implement it correctly.
Could someone please explain what is the difference between
socket.disconnect(); and io.of('/').adapter.remoteDisconnect();
If I initialise my io with:
io.adapter(redisIO({
host: config.server.redis.host,
port: config.server.redis.port,
requestsTimeout: config.server.redis.request_timeout
}));
Shouldn't then socket.disconnect(); be aware of using redisIO? If using remoteDisconnect can I still capture socket.on('disconnect', fn) or should remoteDisconnect be called in socket.on('disconnect', fn)?
What happens if client disconnects? How can I propagate it to socket.io cluster?
Any working examples will be appreciated :)
Thanks!
Capture the socket event disconnecting, not disconnect, by then it's too late!
socket.on('disconnecting', () => {
var room_name = sess.id
io.of('/').adapter.remoteDisconnect(room_name, true, err => {
delete socket.rooms[room_name]
socket.removeAllListeners()
})
})

Socket.io 1.0 - Event to room only broadcastet, I want to emit to everyone (including sender)

according to the new docs:
simply use to or in (they are the same) when broadcasting or emitting:
io.to('some room').emit('some event');
And it works like expected in a context like
socket.on('event', function (data) {
//do some action
socket.to('room').emit('response_event', data);
});
But I want to send 'some event' not only to the other participants in the room but also to the sender himself.
According to previous versions, I expected a behavior like
io.to('some room').broadcast('some event'); //to everyone else
io.to('some room').emit('some event'); //to everyone else and sending socket
As a workaround, I first sent the event to the sending socket, then broadcast it. But that seems dirty to me
socket.on('event', function (data) {
//do some action
socket.emit('response_event', data);
socket.to('room').emit('response_event', data);
});
Do you have any suggestions?
socket.to('room').emit works like the former broadcast (send to everyone except sender).
io.sockets.to('room').emit emits to everyone in room.
for namespaces use io.of('/namespace').to('room').emit
Source: personal experience after having searched the docs for quite some time.

In Socket.IO, is 'heartbeat' an event that can be used to trigger other actions?

This exact code doesn't work, but, I was hoping something like it was:
io.sockets.on('connection', function(socket) {
socket.on('heartbeat', function() {
// Do something here...
});
});
Is something like this possible? I mean, I know I can just make a different function that triggers every, say, 15 seconds using a setInterval:
io.sockets.on('connection', function(socket) {
setInterval(function() {
// Do something
},15000);
});
But since the heartbeat is already running at this interval, why not make use of it?
In any case, any insight would be greatly appreciated.
I think that I see what you're trying to do. There are a few exposed events that you can check here - list of Socket.io events - but there is no "heartbeat" event that you can tap into to fire at a set interval.
You're on the right track with the second piece of code -
setInterval(function() {
socket.emit('heartbeat', someData);
}, 5000);
And on the client side -
socket.on('heartbeat', function(data) {
console.log(data);
})

Disconnect All Users of Room when "Host" Disconnects in Socket.IO

Currently I have the originator of a room marked as the "Host".
I need to set it so that if the "Host" clicks a "Close Room" link, it will disconnect all over users from that room id.
How can I grab all users from socket.manager.roomClients or something of the sorts, loop through them all and run some type of socket.leave( room_id ) if the "Host's" room_id matches the key in the socket manager?
Thanks for any insight or help. Let me know if I need to clarify anything.
There doesn't appear to be a mechanism for this in socket.io, but it's not terribly difficult to implement it yourself. You just iterate over each socket in the room and call the disconnect method. This would ideally be a io.sockets level method, but you've got to know the namespace that the socket is using, so I added a prototype at the socket level to boot everyone out of a room. Take a look at the following:
var sio = require('socket.io');
var io = sio.listen(app);
sio.Socket.prototype.disconnectRoom = function (name) {
var nsp = this.namespace.name
, name = (nsp + '/') + name;
var users = this.manager.rooms[name];
for(var i = 0; i < users.length; i++) {
io.sockets.socket(users[i]).disconnect();
}
return this;
};
You can use it as shown below.
socket.on('hostdisconnect', function() {
socket.disconnectRoom('roomName');
});
A word of warning, if you're going to use something like this, it's important to be aware it uses internal data structures which may or may not be around in the next version of socket.io. It's possible for an update from socket.io to break this functionality.
The latest update in socket.io is the leave() method as a companion to join().
Eg;
socket.join('room1');
socket.leave('room1');
May be this help you in your scenario.
Here is how I managed to achieve this in socket.io "version": "2.1.1" :
function disconnectRoom(room: string, namespace = '/') {
io.of(namespace).in(room).clients((err, clients) => {
clients.forEach(clientId => this.io.sockets.connected[clientId].disconnect());
});
}
After much fighting with trying to do it through socket.io I figured out a way to get the room to be killed through Node.JS/Express
app.get('/disconnect', function(req, res){
console.log("Disconnecting Room " + req.session.room_id);
req.session.destroy(function(err){
if (err){
console.log('Error destroying room... ' + err);
} else{
res.redirect('/');
}
});
});

Resources