I have many functions where I need use socket.io but I want organize connection only once. Users are connected like this:
exports.sendInvite = function(io) {
let usersMap = new Map;
io.on('connection', function(socket) {
console.info(`client connected socketId = ${socket.id}`);
console.log("session_id: " + socket.request.session.session_id);
usersMap.set(socket.request.session.session_id, socket.id);
console.log("Map size: " + usersMap.size);
//some actions....
//and disconnect
socket.on('disconnect', function(){
usersMap.delete(socket.request.session.session_id);
console.log('user disconnected');
console.log("Map size: " + usersMap.size);
});
});
}
But I have another functions where I need use socket.io. How can I connect users only once and use their socket.id many times in other functions. Please, help me.
Related
so there is my code i am trying to create chatroom with Socket.io with rooms (one-to-one random chatroom) but i think there is bug because when i connect first two sockets it works perfectly but when i connect third socket it does not work anymore i think it is because of "numb++" but i don't know how to correct it because i have not many experience in rooms. i wanna implement : chat between 2 socket and when third client joins i wanna create second room and wait for forth socket to join to chat and etc. , and u i know i wanna one to one random chatroom like Omegle.
var numb = 1;
var chnm = io.of('/STchat')
app.get('/STchat', function(req, res){
res.sendFile('C:\\Users\\tuna\\Desktop\\JUSTFOL\\views\\Tchat.html')
chnm.once('connect', function(socket){
socket.join("room" + numb)
console.log('made socket connection', socket.id);
chnm.in("room" + numb).clients(function(err, clients){
if(clients.length > 2) {
numb++
}
});
socket.on('chat', function(data) {
chnm.in("room" + numb).emit('chat',data)
})
socket.on('disconnect', function(){
console.log('socket disconnected')
});
}
});
app.get('/StvChat', function(req ,res){
res.sendFile(__dirname + '/views/VideoC.html');
});
var socket = io.connect('http://localhost:5000/STchat')
var message = document.getElementById('message');
handle = document.getElementById('handle');
btn = document.getElementById('send');
output = document.getElementById('output');
typing = document.createElement('p');
typing.className = "tycl";
input = document.getElementById("message");
$('form').submit(function(){
socket.emit('chat',{
message: message.value,
});
$('#message').val('');
return false;
});
input.addEventListener("keyup", function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById("send").click();
}
});
socket.on('chat', function(data){
output.innerHTML += '<p>' +' '+ data.message +'</p>'
});
This was too long to fit in the comments so I have added as an answer. To clarify, here is an issue I am seeing in the way you are emitting the chat event. Lets walk through a scenario.
var numb = 1;
Two users (User A, and User B) connect to the socket and are put into room "room1". Now, numb should be incremented by your code and now numb will be == 2.
Now, User A (who is in "room1") emits a "chat" event. Here is the issue I see:
socket.on('chat', function(data) {
chnm.in("room" + numb).emit('chat', data)
})
User A's chat event is emitted to "room2" but User A is in "room1". This happens because numb == 2 at this point in the scenario and you are using numb to emit that event, basically this is what happens chnm.in("room" + 2). User B does not get User A's emit, because it was sent to the wrong room (room2). If I misunderstood what you are trying to do please let me know.
EDIT: As requested here is some modifications to your code that I have tested locally with success. Two users per each room.
var numb = 1;
var chnm = io.of('/STchat');
app.get('/STchat', function(req, res) {
res.sendFile('C:\\Users\\tuna\\Desktop\\JUSTFOL\\views\\Tchat.html');
chnm.once('connect', function(socket) {
// store the room in a var for convenience
var room = "room" + numb;
// join socket to the next open room
socket.join(room);
// store room on socket obj for use later - IMPORTANT
socket.current_room = room;
// log some stuff for testing
console.log('made socket connection', socket.id);
console.log("Joined room: ", socket.current_room);
// Check room occupancy, increment if 2 or more
chnm.in(room).clients(function(err, clients) {
if (clients.length >= 2) {
numb++;
}
});
socket.on('chat', function(data) {
// emit to that sockets room, now we use that current_room
chnm.in(socket.current_room).emit('chat', data);
});
socket.on('disconnect', function() {
console.log('socket disconnected');
});
});
});
app.get('/StvChat', function(req, res) {
res.sendFile(__dirname + '/views/VideoC.html');
});
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 using socket.io for private chatting for the server side I am using
socket.broadcast.to(receiver_socket_id).emit('message', data); // where data is a json object containing text
And at the client side code I catch the data using
socket.on('message', function (data) {
alert(data. text);
});
Its working properly and showing the alert on that specific user (socket id) ‘s panel when only two socket are connected (sender and receiver). But the problem appears when one more user connects to that socket then I see two alerts and when total 4 user connected (sender + receiver + two others) then see 3 alerts. But the good point is I can see the alerts only that specific client's panel not the others.
I can’t understand the problem, please help.
Please have a look on it
gyazo.com/a98d3a64a9fc6487e6ded8ccd90fd5ab
it prints test three times because three browsers are opened.
Full code here:
Sever side (I have used Redis):
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
server.listen(8080);
var usernames = {};
io.on('connection', function (socket) {
console.log(socket.id);
socket.on('adduser', function (userId) {
usernames[userId] = socket.id;
});
var redisClient = redis.createClient();
redisClient.subscribe('message-channel');
redisClient.on('message', function (channel, data) {
var jsonObj = JSON.parse(data);
var rcvrId = jsonObj.rcvrId;
socket.broadcast.to(usernames[rcvrId]).emit('message', data); // Not throwing error....should work
});
socket.on('disconnect', function () {
console.log(socket.id + ' Disconnected');
redisClient.quit();
});
});
Client side:
var socket = io.connect('http://localhost:8080');
var userId = $('input[name="userId"]').val();
var rcvrId = $('input[name="rcvrId"]').val();
socket.on('connect', function () {
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser', userId);
});
socket.on('message', function (data) {
data = jQuery.parseJSON(data);
console.log(data);
$("#messages").append("<div><strong>" + data.userId + " : </strong><span>" + data.message + "</span></div>");
});
You can use io.of('/').sockets[rcvrId].emit('message', data). In case you are using a different namespace just replace the / with your namespace.
I have the following situation and just wanted to check if I am doing it right. I have a couple of devices at my customers (RS232). Now I have a RS232-WIFI dongle connected with it, so data out of the device is sent over to my server (it outputs a datastring, example: {12,1,etc). On my server I have a NodeJS script running, that opens up a port and fetches all data coming in.
var net = require('net');
var host = '1.1.1.1';
var servers = [];
var ports = [20000, 20001, 20002, 20003, 20004];
// Create servers
ports.forEach(function (port) {
var s = net.createServer(function (sock) {
// We have a connection - a socket object is assigned to the connection automatically
console.log('CONNECTED (' + sock.localPort + '): ' + sock.remoteAddress + ':' + sock.remotePort);
// Add a 'data' event handler to this instance of socket
sock.on('data', function (data) {
// post data to a server so it can be saved and stuff
postData(data.toString(), sock);
// close connection
sock.end();
});
sock.on('error', function (error) {
console.log('******* ERROR ' + error + ' *******');
// close connection
sock.end();
});
});
s.listen(port, host, function () {
console.log('Server listening on ' + host + ':' + s.address().port);
});
servers.push(s);
});
Okay, so this works pretty good. But I am wondering, sometimes not all of the data is posted at once, sometimes I get {12, and after a second I get the rest (or even more times is needed). What can I do to optimize this script further? Do I need to call sock.end(); after receiving data? Does this hurt network performance for me or my customers?
If you guys need more info let me know.
That depends on the protocol of your devices, if the devices use each connection for a chunk of data, you can write the program like so: (Do not close the socket on data event)
....
// socket will close and destroy automatically after the device close the connection
var s = net.createServer(function (sock) {
sock.setEncoding('utf8');
var body = "";
sock.on('data', function (data) {
body = body + data;
});
sock.on('end', function() {
console.log(data);
postData(data);
});
// TODO error handling here
});
....
Note: Socket is not guaranteed to give you all data at once, you should listen data event then concat all chunks before using.
If your devices don't close socket, you will not receive on('end'), then the code should be like this:
....
var s = net.createServer(function (sock) {
sock.setEncoding('utf8');
// var body = "";
sock.on('data', function (data) {
// body = body + data;
postData(data);
});
sock.on('end', function() {
console.log('end');
});
// TODO error handling here
});
....
When a user disconnects from the server, how can I find out the session ID?
At the moment I’ve got an ugly method of asking all existing clients to send a message back.
e.g. on the server:
socket.on('disconnect', function() {
// What’s the sessionid?
});
You can attach any data to socket when connection is made:
var clients = {}
var client_id = 0;
io.sockets.on('connection', function (socket) {
socket.client_id = client_id; // or your `session_id`
socket.anyData = "foobar";
clients[client_id] = socket;
client_id++;
socket.on("disconnect", function() {
console.log(this.anyData) // prints: foobar
delete clients[this.client_id];
}
}
socket.on('disconnect', function() {
console.log(this.id);
});
will give you the ID of the socket which was closed, but this is probably more of a hack... :)