I am creating a game using socket io. A player connects like this:
var playerName = document.getElementById("name").value;
socket.emit('setup player', {
name : playerName
});
Then on the server, the player is setup and his information is sent back to the client:
function onSetupPlayer(data) {
...
var newPlayer = new Player(x, y, color, data.name,
this.id, scale);
socket.emit('setup game', {
localPlayer : newPlayer
});
...
sockets[this.id] = socket;
}
The following call:
socket.emit('setup game', {
localPlayer : newPlayer
});
Should send the setup data only back to the client that requested the setup to be done originally. However the setup call gets send to everyone in the lobby.
Could this have anything to do with the fact that I am using localhost to test it? I am also testing it on the same machine by using different tabs. If this is what is causing the issue, is there a way to resolve it? Since this is pretty annoying when testing my game.
EDIT:
Initialization:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var socket = require('socket.io')(http);
var path = require('path');
var io = require('socket.io')(80);
...
var setEventHandlers = function() {
socket.sockets.on("connection", onSocketConnection);
};
Listening for connection:
function onSocketConnection(client) {
...
client.on("setup player", onSetupPlayer);
...
};
And on the client side I have this:
var setEventHandlers = function() {
socket.on("setup game", onSetupGame);
...
}
socket.emit send event to everyone excepts this. To send data back to this user try
io.to(socket).emit()
Related
I'm using Socket.IO for websockets and I want clients receive a welcome message in console from server when they connect but it's not working:
Server:
var fs = require('fs');
var https = require('https');
var express = require('express');
var app = express();
var options = {
key:
fs.readFileSync('/myfolder/mykey.pem'),
cert:
fs.readFileSync('/myfolder/mychain.pem')
};
var serverPort = 3080;
var server = https.createServer(options,app);
var io = require('socket.io')(server);
app.get('/',function(req,res){
res.sendFile(__dirname+'/index.html');
});
server.listen(serverPort, function(){
console.log('Server is working');
//console.log(__dirname);
});
io.on('connection', function(socket){
console.log("Connected!");
socket.broadcast.emit("Welcome","Good day sunshine!");
});
Client:
<script src="https://localhost:3080/socket.io/socket.io.js"></script>
<script>
var URL_SERVER = 'https://localhost:3080';
var socket = io.connect(URL_SERVER);
socket.on("Welcome", function(data){
console.log(data);
});
</script>
I'm getting message console in server side but not the server answer in the console client.
How can I fix it?
To broadcast, simply add a broadcast flag to emit and send method
calls. Broadcasting means sending a message to everyone else except
for the socket that starts it.
Reference : https://socket.io/docs/
i want to send a websocket, using express-ws out from a different controller, not by route and I have the following code in the server.js:
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
app.ws('/', SocketController.socketFunction);
the SocketController looks like that:
exports.socketFunction = function (ws, req) {
ws.on('message', function(msg) {
console.log(msg);
ws.send("hello");
});
}
Is it possible to call the
ws.send()
event from another controller? How do i get the "ws" object?
thanks!
You will have to store your sockets in memory. To access stored sockets from different modules, you can store references for these sockets in a separate module.
For example, you can create a module socketCollection that stores all the active sockets.
socketCollection.js:
exports.socketCollection = [];
You can import this module where you define your web socket server:
var socketCollection = require('./socketCollection');
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
expressWs.getWss().on('connection', function(ws) {
socketCollection.push({
id: 'someRandomSocketId',
socket: ws,
});
});
app.ws('/', SocketController.socketFunction);
Now every time new client connects to the server, it's reference will be saved to 'socketCollection'
You can access these clients from any module by importing this array
var socketCollection = require('./socketCollection');
var ws = findSocket('someRandomSocketId', socketCollection);
var findSocket = function(id, socketCollection) {
var result = socketCollection.filter(function(x){return x.id == id;} );
return result ? result[0].socket : null;
};
Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.
I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.
Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.
var myemail = "email#gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.
var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables
var myemail = "email#gmail.com";
var device_id = '12345';
var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');
//Connect listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
Any ideas?
UPDATE
Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).
debugging output image link
Solved this - issue was that the server I was connecting to required use of https, so I needed to add
{secure: true, rejectUnauthorized: false}
after the url to connect to.
Full working example:
const myemail = email#email.com;
const device_id = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true, rejectUnauthorized: false});
function doStuff(){
//Listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "003021");
}
doStuff();
I think the line causing the issue is :
var socket = io.connect('https://example.net:3000');
I managed to make a working example using this code :
const myemail = "email#gmail.com";
const device_id = '12345';
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
try{
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
}catch(e){ console.log(e); }
});
OK let's say I have a simple server set up like this:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var lobby = io.of('/lobby');
lobby.on("connection", function (socket) {
console.log("Successful connection lobby");
socket.on("disconnect", function () {
console.log("Successful disconnect lobby");
});
});
I have noticed that if a user just stays plugged into the system they are eventually dropped. I thought I could do something with the namespace, where I use a chron job, on a 5 minute interval, to do lobby.emit('ping') and all the clients connected would have an
.on('ping', new Emitter.Listener() {
#Override
public void call(Object... args) {
lobby.emit('pong');
}
});
and the server would have a .on('pong', function() {}); that effectively is a blank function. Is there another/better way to keep the system from timing out people who are not active?
I've got an Adobe AIR Application on the local machine that communicates with an remote node.js server script (socket-script.js) via socket connection.
Furthermore i start a new node.js process through command line and send some additional arguments to a second server script (terminal-script.js).
Question: How can i send the arguments from the terminal-script.js to socket-script.js? Afterwards the socket-script.js should broadcast the
args to the AIR Application. Anyone an idea how to connect the two independent running processes in Node.js? Thanks.
Illustration link
Use the server to communicate between processes:
socket-script.js
var net = require('net');
var app = null;
var server = net.createServer(function(socket) {
socket.on('data', function(data){
if(data.indexOf('terminal:') >-1){
if(app){
app.write(data);
}
} else if(data.indexOf('app:') >-1){
app = socket;
}
});
});
terminal-script.js:
var net = require('net');
var client = net.connect({port: 9001}, function() {
client.write('terminal:' + process.argv[2]);
});
app:
var net = require('net');
var client = net.connect({port: 9001}, function() {
client.write('app:connect');
});
client.on('data', function(data){
if(data.indexOf('terminal:') >-1){
// got terminal data
}
});
The only way that I conceive of to make this work is something like this:
1) You'll need to have terminal-script.js be listening on a socket. Like so:
var arguments = process.args.splice(2);
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(arguments[0]);
}).listen(8000, '127.0.0.1');
2) Just make a request from socket-script to the terminal script:
//somewhere in socket-script use this to grab the value from the terminal script.
var http = require('http');
var options = {
host: 'terminal-script-host.com',
port: '8000',
path: '/'
};
var req = http.get(options, function(res) {
res.on('data', function (data) {
console.log('socket-script got the data from terminal-script: ' + data);
});
});
Not sure if this helps. But I can tell you that it would be nearly impossible to "inject" something into the socket-script from the terminal-script, not in a way that would work with the same request anyways.