I am making a control panel for my Minecraft mining turtle and I need to communicate between the two using websockets. I have troubleshooted the Lua side of things and that works as intended when I connected it to a echo server.
Code here:
local ws,err = http.websocket("wss://localhost:5757")
if ws then
ws.send("Hello")
print(ws.receive())
ws.close()
end
However, I can not get the NodeJS side to work. I have tried different ports, I've tried opening ports.
Code here:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 5757 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('testing 123');
});
I can't figure out where I have gone wrong. All help is appreciated.
EDIT: Thought I'd add that it's not giving errors either, that I am using the ws npm package and running the latest LTS node version.
EDIT 2: I tried this code example here
const WebSocket = require('ws');
const ws = new WebSocket('wss://echo.websocket.org/');
ws.on('open', function open() {
ws.send('testing 123');
});
ws.on('message', function incoming(data) {
console.log(data);
});
And it worked and replied with 'testing 123' so it seems that the web socket doesn't want to run on local host.
I'm new to Socket.io. Here is my problem.
I want to get the real time location of Android device. So I created a simple app to get current GPS location. And Node.js server and also Angular Admin panel.
Here is my Node.js server code.
//Some import statements are missing here. Not added.
var app = require('express')();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
// Creating the socket connection.
io.sockets.on('connection', function (socket) {
socket.on('join', function (data) {
socket.join(data.id);
});
});
module.exports = function (app, express) {
var api = express.Router();
api.post('/device_location/:child_id', function (req, res) {
var child_id = req.body.child_id;
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'}); //Sending request to registered android device.
var gps_location = ""; //Here i want to take GPS data from android client.
res.json({ type: "success", code: 200, data: gps_location }); //Then i can send the response to anyone who need that.
});
return api;
};
If this is not clear, please check this gist : https://gist.github.com/chanakaDe/123080fa5427c38c37f36afdac10be7c
First I created the socket connection. Then Android client can connect to it with unique user ID.
Then I'm sending the request to get GPS data when admin press the button from the Administration button.
io.sockets.in(child_id).emit('new_msg', {msg: 'gps_data'});
Here, child_id is the ID of android application.
Then I want to get the response from Android app and read it in server.
After reading that, I can send that to anyone asking for it.
res.json({ type: "success", code: 200, data: gps_location });
This is the normal Node.js way of sending a response.
How can we get the response to this var gps_location = ""; variable which we are getting GPS value of specific user.
Please help me on this. Tried many ways, but not good. I just need to read the response from Android client in the server and process it.
You need to emit your GPS location from Android to your server using something like :
socket.emit("gpsdata", data)
and then receive it in Node using socket.on("gpsdata", doSomething) :
io.sockets.on('connection', socket => {
socket.on("gpsdata", data => { // Receive data from one socket
io.sockets.emit('gps_location', { gps_location : data }) // Emit to everyone
})
});
https://socket.io/docs/emit-cheatsheet/
I have a NodeWebkit client which connects to a nodejs server using the socket.io library (JavaScript).
The client launches the connect procedure on the application start but the server does not acknoledge any connections... Though the client's socket has the connected attribute to "true".
You should know that I am using socketio-jwt to authentificate the connection.
Github: https://github.com/auth0/socketio-jwt
I know that the connection does work in a way because if I add :
io.sockets.on('connection', function(){console.log("hello");})
It prints hello !
So it seems that event though the connection is somehow made it doesn't want to do the auth part with the library, resulting in... Well... Nothing.
But that's not all !!
Because if I reboot the app (not the server) then the auth works most of the time ! It acts like a race condition... But I dont see how it could possibly be one... Every line of code is geting executed appart of the success callback of authentification.
I tried connecting to a remote server and on my localhost.
I also tried with an other library of socket auth but I've got the same probleme.
This is the server code:
var session = require('express-session');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketioJwt = require('socketio-jwt');
io.sockets.on('connection', socketioJwt.authorize({
secret: 'some secret',
timeout: 15000 // 15 seconds to send the authentication message
})).on('authenticated', function (socket) {
console.log('[Info]: A user connected to socket = ', socket.decoded_token);
});
});
http.listen(5000, function () {
console.log('listening on *:5000');
});
And now the client code:
this.socket = io.connect('http://' + that.hostName +':' + that.port);
var token = jwt.sign({email: "someEail", pwd: "somePwd"}, fromServerSecret);
this.socket.on('connect', function () {
that.socket.emit('authenticate', {token: token}) //send the jwt
.on('authenticated', function () {
console.log("[Info]: Socket login successfull");
})
.on('unauthorized', function (msg) {
console.log("[Warning]: Socket unauthorized: " + JSON.stringify(msg.data));
throw new Error(msg.data.type);
});
});
The server side log "A user connected to socket" is never shown.
If you have an idear ! Thanks for your time.
Why is there a 'that' on socket.emit (client)? I think you should handle it within the same instance of socket.io - using same 'this' as above
I have a Kik bot that I am hosting on my computer. I setup the configureation with the following code:
let request = require('request')
request.post('https://api.kik.com/v1/config',
{
"auth":{
"user":"bhs************",
"pass":"*******-*****-*****-****"
},
"headers":{
"User-Agent":"request"
},
"form":{
"webhook":"https://(my public ip):8080",
"features":{
"manuallySendReadReceipts":false,
"receiveReadReceipts":false,
"receiveDeliveryReceipts":false,
"receiveIsTyping":false
}
}
});
And here is the code for my actual bot:
'use strict';
let util = require('util');
let https = require('https');
let Bot = require('#kikinteractive/kik');
// Configure the bot API endpoint, details for your bot
let bot = new Bot({
username: 'bhs************',
apiKey: '*******-*****-*****-****',
baseUrl: 'https://(my public ip):8080'
});
bot.updateBotConfiguration();
bot.onTextMessage((message) => {
console.log("New Message")
message.reply(message.body);
});
// Set up your server and start listening
let server = https
.createServer(bot.incoming())
.listen(8080);
console.log("Server Running on port 8080")
I have setup port forwarding on my router to redirect to my computer with the internal and external port of 8080. I also have the protocol set to both TCP and UDP. Here is a photo if that setup:
My bot has stopped telling me that I need to Finnish setting it up every time I text it, but now it never says anything. Is there something that I'm doing wrong here?
It sounds like its not hitting your endpoint properly. I would suggested using ngrok to give yourself a public URL and it will forward to your local IP.
https://ngrok.com/
I'm working with socket.io and node.js and until now it seems pretty good, but I don't know how to send a message from the server to an specific client, something like this:
client.send(message, receiverSessionId)
But neither the .send() nor the .broadcast() methods seem to supply my need.
What I have found as a possible solution, is that the .broadcast() method accepts as a second parameter an array of SessionIds to which not send the message, so I could pass an array with all the SessionIds connected at that moment to the server, except the one I wish send the message, but I feel there must be a better solution.
Any ideas?
Ivo Wetzel's answer doesn't seem to be valid in Socket.io 0.9 anymore.
In short you must now save the socket.id and use io.sockets.socket(savedSocketId).emit(...) to send messages to it.
This is how I got this working in clustered Node.js server:
First you need to set Redis store as the store so that messages can go cross processes:
var express = require("express");
var redis = require("redis");
var sio = require("socket.io");
var client = redis.createClient()
var app = express.createServer();
var io = sio.listen(app);
io.set("store", new sio.RedisStore);
// In this example we have one master client socket
// that receives messages from others.
io.sockets.on('connection', function(socket) {
// Promote this socket as master
socket.on("I'm the master", function() {
// Save the socket id to Redis so that all processes can access it.
client.set("mastersocket", socket.id, function(err) {
if (err) throw err;
console.log("Master socket is now" + socket.id);
});
});
socket.on("message to master", function(msg) {
// Fetch the socket id from Redis
client.get("mastersocket", function(err, socketId) {
if (err) throw err;
io.sockets.socket(socketId).emit(msg);
});
});
});
I omitted the clustering code here, because it makes this more cluttered, but it's trivial to add. Just add everything to the worker code. More docs here http://nodejs.org/api/cluster.html
each socket joins a room with a socket id for a name, so you can just
io.to('socket#id').emit('hey')
docs: http://socket.io/docs/rooms-and-namespaces/#default-room
The simplest, most elegant way
verified working with socket.io v3.1.1
It's as easy as:
client.emit("your message");
And that's it. Ok, but how does it work?
Minimal working example
Here's an example of a simple client-server interaction where each client regularly receives a message containing a sequence number. There is a unique sequence for each client and that's where the "I need to send a message to a particular client" comes into play.
Server
server.js
const
{Server} = require("socket.io"),
server = new Server(8000);
let
sequenceNumberByClient = new Map();
// event fired every time a new client connects:
server.on("connection", (socket) => {
console.info(`Client connected [id=${socket.id}]`);
// initialize this client's sequence number
sequenceNumberByClient.set(socket, 1);
// when socket disconnects, remove it from the list:
socket.on("disconnect", () => {
sequenceNumberByClient.delete(socket);
console.info(`Client gone [id=${socket.id}]`);
});
});
// sends each client its current sequence number
setInterval(() => {
for (const [client, sequenceNumber] of sequenceNumberByClient.entries()) {
client.emit("seq-num", sequenceNumber);
sequenceNumberByClient.set(client, sequenceNumber + 1);
}
}, 1000);
The server starts listening on port 8000 for incoming connections. As soon as a new connection is established, that client is added to a map that keeps track of its sequence number. The server also listens for the disconnect event to remove the client from the map when it leaves.
Each and every second, a timer is fired. When it does, the server walks through the map and sends a message to every client with their current sequence number, incrementing it right after. That's all that is to it. Easy peasy.
Client
The client part is even simpler. It just connects to the server and listens for the seq-num message, printing it to the console every time it arrives.
client.js
const
io = require("socket.io-client"),
ioClient = io.connect("http://localhost:8000");
ioClient.on("seq-num", (msg) => console.info(msg));
Running the example
Install the required libraries:
npm install socket.io#3.1.1 socket.io-client#3.1.1
Run the server:
node server
Open other terminal windows and spawn as many clients as you want by running:
node client
I have also prepared a gist with the full code here.
Well you have to grab the client for that (surprise), you can either go the simple way:
var io = io.listen(server);
io.clients[sessionID].send()
Which may break, I doubt it, but it's always a possibility that io.clients might get changed, so use the above with caution
Or you keep track of the clients yourself, therefore you add them to your own clients object in the connection listener and remove them in the disconnect listener.
I would use the latter one, since depending on your application you might want to have more state on the clients anyway, so something like clients[id] = {conn: clientConnect, data: {...}} might do the job.
You can use
//send message only to sender-client
socket.emit('message', 'check this');
//or you can send to all listeners including the sender
io.emit('message', 'check this');
//send to all listeners except the sender
socket.broadcast.emit('message', 'this is a message');
//or you can send it to a room
socket.broadcast.to('chatroom').emit('message', 'this is the message to all');
In 1.0 you should use:
io.sockets.connected[socketid].emit();
Whatever version we are using if we just console.log() the "io" object that we use in our server side nodejs code, [e.g. io.on('connection', function(socket) {...});], we can see that "io" is just an json object and there are many child objects where the socket id and socket objects are stored.
I am using socket.io version 1.3.5, btw.
If we look in the io object, it contains,
sockets:
{ name: '/',
server: [Circular],
sockets: [ [Object], [Object] ],
connected:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
here we can see the socketids "B5AC9w0sYmOGWe4fAAAA" etc. So, we can do,
io.sockets.connected[socketid].emit();
Again, on further inspection we can see segments like,
eio:
{ clients:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
So, we can retrieve a socket from here by doing
io.eio.clients[socketid].emit();
Also, under engine we have,
engine:
{ clients:
{ B5AC9w0sYmOGWe4fAAAA: [Object],
'hWzf97fmU-TIwwzWAAAB': [Object] },
So, we can also write,
io.engine.clients[socketid].emit();
So, I guess we can achieve our goal in any of the 3 ways I listed above,
io.sockets.connected[socketid].emit();
OR
io.eio.clients[socketid].emit();
OR
io.engine.clients[socketid].emit();
You can do this
On server.
global.io=require("socket.io")(server);
io.on("connection",function(client){
console.log("client is ",client.id);
//This is handle by current connected client
client.emit('messages',{hello:'world'})
//This is handle by every client
io.sockets.emit("data",{data:"This is handle by every client"})
app1.saveSession(client.id)
client.on("disconnect",function(){
app1.deleteSession(client.id)
console.log("client disconnected",client.id);
})
})
//And this is handle by particular client
var socketId=req.query.id
if(io.sockets.connected[socketId]!=null) {
io.sockets.connected[socketId].emit('particular User', {data: "Event response by particular user "});
}
And on client, it is very easy to handle.
var socket=io.connect("http://localhost:8080/")
socket.on("messages",function(data){
console.log("message is ",data);
//alert(data)
})
socket.on("data",function(data){
console.log("data is ",data);
//alert(data)
})
socket.on("particular User",function(data){
console.log("data from server ",data);
//alert(data)
})
As of version 1.4.5, be sure you provide a properly prefixed socketId in io.to().
I was taking the socketId the Client logged to debug and it was without prefix so I ended up searching forever till I found out! So you might have to do it like this if the Id you have is not prefixed:
io.to('/#' + socketId).emit('myevent', {foo: 'bar'});
io.sockets.sockets[socket.id].emit(...) worked for me in v0.9
Also you can keep clients refferences. But this makes your memmory busy.
Create an empty object and set your clients into it.
const myClientList = {};
server.on("connection", (socket) => {
console.info(`Client connected [id=${socket.id}]`);
myClientList[socket.id] = socket;
});
socket.on("disconnect", (socket) => {
delete myClientList[socket.id];
});
then call your specific client by id from the object
myClientList[specificId].emit("blabla","somedata");
Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths.
This might help:
http://socket.io/docs/rooms-and-namespaces/