I have WebSocketServer listening to connecting clients. Unfortunately I can't find a way to check which client has closed a connection.
In
ws.on('close',function(){ });
how can I check which user ws belongs to?
var WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 8080});
var playersConnected=[];
var playersConnectedByID=[];
var playersConnectedBySock=[];
wss.on('connection', function(ws) {
console.log("somebody connected");
playerID=Math.floor(Math.random() * (100000000 - 0+1) + 0);
playerID=playerID.toString();
ws.send("newID="+playerID);
//inserting new player into the right place
l=playersConnected.length; console.log("Current array length is "+l);
playersConnected[l]=([playerID,ws,"free"]);
l=playersConnected.length;
for(i=0;i<l;i++) console.log(i+" "+playersConnected[i][0]);
console.log("=================================================");
ws.on('close',function(){console.log("closing ");});
ws.on('message', function(message) {
console.log('%s send received mess %s',playerID,message);
}
);
});
process.on('uncaughtException', function (err) {
console.log("bad connect");
console.log(err);
});
Every function forms a closure for local variables, so you could just use an object which contains all necessary informations:
wss.on('connection', function(ws) {
var playerID = Math.floor(Math.random() * (100000000 - 0+1) + 0);
playerID = playerID.toString();
var connection = {
socket: ws,
playerID: playerID
};
console.log("connected",connection);
// add your other code here
ws.on('close',function(){
console.log("closing ", connection);
// you will probably change this to remove_from_userlist() or similar
});
});
Related
I am very beginner in NodeJS, I am taking data from S71200 PLC device using nodes7 library, I want to pass data using socket io emit but I can't pass data to socket io emit below my code
app.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var nodes7 = require('nodes7'); // This is the package name, if the repository is cloned you may need to require 'nodeS7' with uppercase S
var conn = new nodes7;
var doneReading = false;
var doneWriting = false;
var variables = {
TEST7: 'DB1,INT2.3',
TEST1: 'DB1,X0.0.3',
TEST2: 'DB1,INT2'
};
conn.initiateConnection({port: 102, host: '127.0.0.1', rack: 0, slot: 1}, connected);
function connected(err) {
if (typeof(err) !== "undefined") {
// We have an error. Maybe the PLC is not reachable.
console.log(err);
process.exit();
}
conn.setTranslationCB(function(tag) {return variables[tag];}); // This sets the "translation" to allow us to work with object names
conn.addItems(['TEST7','TEST1']);
//conn.writeItems('TEST2', 90, valuesWritten);
setInterval(function(){
conn.readAllItems(valuesReady);
},1000)
}
function valuesReady(anythingBad, values) {
if (anythingBad) { console.log("SOMETHING WENT WRONG READING VALUES!!!!"); }
console.log(values.TEST1[0],values.TEST1[1],values.TEST1[2],values.TEST7[0],values.TEST7[1],values.TEST7[2]);
//console.log( typeof(temp));
doneReading = true;
}
function valuesWritten(anythingBad) {
if (anythingBad) { console.log("SOMETHING WENT WRONG WRITING VALUES!!!!"); }
console.log("Done writing.");
doneWriting = true;
}
io.on('connection',function(socket){
console.log('one user connected '+socket.id);
socket.emit("channelname", {
message: "Passing S71200 data"
});
socket.on('disconnect',function(){
console.log('one user disconnected '+socket.id);
});
})
http.listen(3000,function(){
console.log('server listening on port 3000');
})
I am using interval function because every second data fetch from PLC device, I got all data from values.TEST1[0],values.TEST1[1],values.TEST1[2],values.TEST7[0],values.TEST7[1],values.TEST7[2] this data passing to
io.on('connection',function(socket){
console.log('one user connected '+socket.id);
socket.emit("channelname", {
message: "Passing S71200 data"
});
socket.on('disconnect',function(){
console.log('one user disconnected '+socket.id);
});
})
Help me to solve this problem
Hey uh I am having an issue and I think this is probably related to net.createserver.
The issue is that whenever the first client joins after that another second client joins, the first client can control the second client and then the first client disconnects because the socket(end) event gets triggered. Is it related to sockets or something or the server can't handle two connections? Please help
The code:
handleGame: function() {
console.log(log.success('The source is starting!'));
var server = net.createServer(function(socket) {
console.log('A client has connected' + "\r\n");
socket.setEncoding('utf8')
global.clientObjz = new client(socket);
game.addClient(clientObjz);
socket.on('data', function(data) {
data = data.toString().split('\0')[0];
console.log('Incoming data: ' + data + "\r\n")
if (data == "<msg t='sys'><body action='verChk' r='0'><ver v='153' /></body></msg>" | data == "<msg t='sys'><body action='rndK' r='-1'></body></msg>" | data.startsWith("<msg t='sys'><body action='login' r='0'>")) {
parseXml(data, function(err, result) {
var type = result.msg['$'].t,
action = result.msg.body[0]['$'].action;
var method = Game.xmlHandlers[type][action];
if (typeof Game[method] == 'function') {
Game[method](data, client);
}
});
}
var dataType = data.charAt(0);
if (dataType == '%') {
game.handleraw(data, clientObjz);
}
});
socket.on('end', function() {
game.removeClient(socket);
console.log('A client has disconnected');
});
socket.on('error', function(err) {
console.log(err);
});
});
server.listen(Game1, "localhost", function() {
console.log('Server is listening on port 6113');
});
}
//this code is another file as i am calling it by game.clients.push
addClient: function(client) {
if (client) {
self.clients.push(client);
}
}
Yes, it's a clubpenguin emulator
full code: https://github.com/dev3211/bingojs
You need to implement socket channels if you are doing this only with NodeJS net.createServer. If you want it simple, you could look for something using express.js, something like this: https://medium.com/factory-mind/websocket-node-js-express-step-by-step-using-typescript-725114ad5fe4
This question already has answers here:
socket.emit in a simple TCP Server written in NodeJS?
(3 answers)
Closed 5 years ago.
I am new to NodeJS and started to learn by building a simple command line chat application. I have the following code for Server and Client. Client-Server communication is successful but I am not able to capture 'adduser' event from the client. Please tell me where I am going wrong.
Server:
var net = require('net');
var chatServer = net.createServer(function(socket){
socket.pipe(socket);
}),
userName="";
chatServer.on('connection',function(client){
console.log("ChatterBox Server\n");
client.write("Welcome to ChatterBox!\n");
client.on('data',function(data){
console.log(""+data);
});
client.on('adduser',function(n){
console.log("UserName: "+ n);
userName = n;
});
});
chatServer.listen(2708);
Client:
var net = require('net');
var client = new net.Socket();
client.connect(2708,'127.0.0.1');
client.on('connect',function(){
client.emit('adduser',"UserName");
});
console.log("Client Connected!\n");
client.on('data',function(data){
console.log(""+data);
});
I guess you don't have to do from the client side :
client.connect(2708,'127.0.0.1');
Just write your client like this is sufficient.
var net = require('net');
var client = new net.Socket();
client.connect(2708, '127.0.0.1',function(){
console.log("Client Connected!\n");
client.emit('adduser',"UserName");
});
client.on('data',function(data){
console.log(""+data);
});
client.on('close', function() {
console.log('Connection closed');
});
So the server side :
var net = require('net');
var sockets = [];
var port = 2708;
var guestId = 0;
var server = net.createServer(function(socket) {
// Increment
guestId++;
socket.nickname = "Guest" + guestId;
var userName = socket.nickname;
sockets.push(socket);
// Log it to the server output
console.log(userName + ' joined this chat.');
// Welcome user to the socket
socket.write("Welcome to telnet chat!\n");
// Broadcast to others excluding this socket
broadcast(userName, userName + ' joined this chat.\n');
socket.on('adduser',function(n){
console.log("UserName: "+ n);
userName = n;
});
// When client sends data
socket.on('data', function(data) {
var message = clientName + '> ' + data.toString();
broadcast(clientName, message);
// Log it to the server output
process.stdout.write(message);
});
// When client leaves
socket.on('end', function() {
var message = clientName + ' left this chat\n';
// Log it to the server output
process.stdout.write(message);
// Remove client from socket array
removeSocket(socket);
// Notify all clients
broadcast(clientName, message);
});
// When socket gets errors
socket.on('error', function(error) {
console.log('Socket got problems: ', error.message);
});
});
// Broadcast to others, excluding the sender
function broadcast(from, message) {
// If there are no sockets, then don't broadcast any messages
if (sockets.length === 0) {
process.stdout.write('Everyone left the chat');
return;
}
// If there are clients remaining then broadcast message
sockets.forEach(function(socket, index, array){
// Dont send any messages to the sender
if(socket.nickname === from) return;
socket.write(message);
});
};
// Remove disconnected client from sockets array
function removeSocket(socket) {
sockets.splice(sockets.indexOf(socket), 1);
};
// Listening for any problems with the server
server.on('error', function(error) {
console.log("So we got problems!", error.message);
});
// Listen for a port to telnet to
// then in the terminal just run 'telnet localhost [port]'
server.listen(port, function() {
console.log("Server listening at http://localhost:" + port);
});
So you've got an object "users" inside the "user" when is connected, push user to the array users but you need to do (server side) on('close', ... to remove the user from users when connected is false ... etc
I am very new to NodeJS and Websockets, but i am trying to play with it.
What i do is read incoming datas from Serial port, then send these datas to a web page using websocket.
From here everything works fine.
I use node-static to serve my web page
I use ws for websocket
The problem is when a client close his browser, then my NodeJS websocket server crashes with the following error :
root#WS-SERVER-2:~/app# node socketserver.js
open serial communication
Client disconnected.
/root/node-v0.10.29/lib/node_modules/ws/lib/WebSocket.js:187
else throw new Error('not opened');
^
Error: not opened
at WebSocket.send (/root/node-v0.10.29/lib/node_modules/ws/lib/WebSocket.js:187:16)
at sendAll (/root/app/socketserver.js:30:16)
at SerialPort.<anonymous> (/root/app/socketserver.js:58:8)
at SerialPort.emit (events.js:95:17)
at Object.module.exports.raw [as parser] (/root/node-v0.10.29/bin/node_modules/serialport/parsers.js:8:13)
at Object.SerialPort.options.dataCallback (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:143:15)
at SerialPortFactory.SerialPort._emitData (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:312:20)
at afterRead (/root/node-v0.10.29/bin/node_modules/serialport/serialport.js:290:18)
at /root/node-v0.10.29/bin/node_modules/serialport/serialport.js:304:9
at Object.wrapper [as oncomplete] (fs.js:459:17)
Here is my websocket/serialport code :
var WebSocketServer = require('../node-v0.10.29/lib/node_modules/ws').Server;
var SerialPort = require('../node-v0.10.29/bin/node_modules/serialport').SerialPort;
var serialPort;
var portName = '/dev/ttyACM0';
var sendData = "";
var wss = new WebSocketServer({port: 8080});
var CLIENTS=[];
wss.on('connection', function(ws) {
CLIENTS.push(ws);
ws.on('message', function(message) {
console.log('received: %s', message);
sendAll(message);
});
ws.on('close', function() {
console.log('Client disconnected.');
});
ws.on('error', function() {
console.log('ERROR');
});
ws.send("");
});
function sendAll(message)
{
for(var i=0;i<CLIENTS.length;i++)
{
CLIENTS[i].send(message);
}
}
serialListener();
function serialListener(debug)
{
var receivedData = "";
serialPort = new SerialPort(portName, {
baudrate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false
});
serialPort.on("open", function () {
console.log('open serial communication');
// Listens to incoming data
serialPort.on('data', function(data) {
receivedData += data.toString();
if (receivedData .indexOf('E') >= 0 && receivedData .indexOf('B') >= 0) {
sendData = receivedData .substring(receivedData .indexOf('B') + 1, receivedData .indexOf('E'));
receivedData = '';
}
// send the incoming data to browser with websockets.
sendAll(sendData);
});
});
}
Can someone help me to figure out what's wrong here ?
I think, you should remove the socket from your CLIENTS array on both close and error event. Otherwise it tries to send a message to a socket that is closed.
I was having this same issue. Turned out I was attempting to send events to sockets that were in the "closing" state. Checking that each socket was specifically open before broadcasting a message fixed it for me:
function sendAll(data){
for(var i = 0; i < clients.length; i++){
if(this.clients[i].readyState != this.clients[0].OPEN){
console.error('Client state is ' + this.clients[i].readyState);
}
else{
this.clients[i].send(data);
}
}
}
Try this while sending data to client:
- socket is my current web socket object.It overwrites the default >WebSocket.js class condition that throws "not-opened error".
if (socket.readyState != socket.OPEN) {
console.error('Client state is ' + socket.readyState);
//or any message you want
} else {
socket.send(JSON.stringify(object)); //send data to client
}
I have the following example of listening to connection and data events, to echo the result back to other telnet clients listening on port 8888. My telnet sessions connect to locahost fine, but no output is echoed. I am hitting my head against a brick wall trying to figure out what is wrong. The execution doesn't even get as far as the 'connect' event.
/server.js
var events = require('events');
var net = require('net');
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join', function (id, client) {
this.clients[id] = client;
this.subscriptions[id] = function (senderId, message) {
if (id != senderId) {
this.clients[id].write(message);
}
}
this.on('broadcast', this.subscriptions[id]);
});
var server = net.createServer(function (client) {
var id = client.remoteAddress + ':' + client.remotePort;
console.log(id);
client.on('connect', function () {
console.log('A new connection was made');
channel.emit('join', id, client);
});
client.on('data', function (data) {
data = data.toString();
channel.emit('broadcast', id, data);
});
});
server.listen(8888);
I then run in the command line
node server.js
telnet 127.0.0.1 8888
When the callback to net.createServer is called, that's because of an implicit connection event. So your code should look like this:
var server = net.createServer(function (client) {
// when this code is run, the connection has been established
var id = client.remoteAddress + ':' + client.remotePort;
console.log('A new connection was made:', id);
channel.emit('join', id, client);
client.on('data', function(data) {
...
});
client.on('end', function() {
...
});
});
The manual has this to say;
net.createServer([options], [connectionListener])
Creates a new TCP server. The connectionListener argument is automatically set as a listener for the 'connection' event.
In other words, your function (client) { already received the connection event, and adding a listener to it when it has already been dispatched has no further effect.