node js xhr polling too much time 25 30 seconds - node.js

I am building an application in this application i add new item for different events from Admin Panel and object just populated by node js socket on frontend and i am getting in few polling request getting two much time.
:4000/socket.io/?EIO=3&transport=polling&t=N6EC8Z7&sid=gKbo2MATsLn2BqtpAAAg
setting i used:-
var io = require('socket.io')(server, { wsEngine: 'ws' });
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
socket.on('JoinEventOneRoom', function(data) {
var id = data.id;
var room = 'notify_event_one_list_'+id;
console.log('Add event one Room Joined sucessfully', room);
socket.join(room);
});
socket.on('JoinEventTwoRoom', function(data) {
var id = data.id;
var room = 'notify_event_two_'+id;
console.log('Delete Event Two Joined sucessfully', room);
socket.join(room);
});
});
React js code
const socket = SocketIOClient(WSC.nodeBaseURL, { transports: ['polling'] });
socket.connect()
Need help what i am missing here.
I am using 2.3.0 version for both socket.io and socket.io-client

Related

Socket.io makes connection on https://domain but doesnt make any on https://domain/route

Okay as I said i the title when I go to my home page the socket connection works perfectly but when I use a route it doesnt work at all here is my index.js
io.of('/admin').on('connection', function(socket) {
console.log('made socket connection', socket.id);
console.log(socket.request.user);
socket.on('chat', async function(data) {
console.log(data);
client.guilds.channels.get('474951005788962846').send(data);
io.sockets.emit('chat', data);
});
});
io.on('connection', function(socket) {
console.log('made socket connection', socket.id);
console.log(socket.request.user);
socket.on('chat', async function(data) {
console.log(data);
client.guilds.channels.get('474951005788962846').send(data);
io.sockets.emit('chat', data);
});
});
and on my /admin page here is my script that it is the same but the connection isnt as I added the /admin
<script>
var socket = io.connect('https://domain/admin');
// Query DOM
var serverID = document.getElementById('add_server_id');
var serverRoles = document.getElementById('add_role_ids');
var btnServer = document.getElementById('add_server_save');
//var output = document.getElementById('output');
// Emit events
btnServer.addEventListener('click', function(){
socket.emit('chat', {
serverid: serverID.value,
serverroles: serverRoles.value
});
});
//Listen for events
socket.on('chat', function(data) {
console.log(data);
//output.innerHTML += '<p><strong>' + data.game + '</strong></p>';
});
</script>
if someone can tell me why is it not connecting I would really appreciate it
var socket = io.connect('https://domain/admin');
to
var socket = io.connect('/admin');
The namespace is an implementation detail of the Socket.IO protocol,
and is not related to the actual URL of the underlying transport,
which defaults to /socket.io/….

Socket.IO duplicated message

I'm trying to build a chat application using Laravel, with node js server, socketio and redis. What I have is this:
Client JS:
var socket = io('http://localhost:3005');
var room = '17';
$("#send").click(function(){
content = $("textarea").val();
id =$("#id").val();
$.ajax({
url: "{{route('send.message')}}",
method: "POST",
data: {content, id, room},
success: function(){
}
});
});
socket.on('cacad', function(message){
console.log(message); //multiple copies here
});
socket.on('connect', function(){
console.log("Connected!");
socket.emit('room', room);
});
Laravel Controller:
public function sendMessage(Request $request){
event(new EventName($request->all()));
$message = new Message;
$message->message = $request->content;
$redis = LRedis::connection();
$redis->publish('chat-channel', json_encode($request->all()));
$message->save();
}
Node Server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var redis = require('ioredis');
var myMessage;
var redis_client = redis.createClient();
redis_client.subscribe('chat-channel');
io.on('connection', function(socket) {
redis_client.on('message', function(channel, message) {
var myData = JSON.parse(message);
socket.broadcast.to('17').emit('cacad', 'u i u a a');
});
socket.on('room', function(room){
socket.join(room);
});
socket.on('disconnect', function(){
console.log("disconnected!");
});
});
http.listen(3005, function() {
console.log('Listening on Port 3005');
});
I am trying to broadcast a message u i u a a in room 17. But when I receive it in the console, it shows multiple copies of it, 2x-4x. In the Laravel controller I publish a message using redis and I subscribe to it in node server. It is received successfully, but the problem lies with the multiple copies of the message (client side).
Please where is it wrong? Thank you :)
I'm pretty convinced I found the issue although I had to search a bit about those simple API usage because I'm not using the library lately.
Looking at the docs it's explain your issue pretty clearly.
Here you are listening to a new connection,
io.on('connection', function(socket) {
If the client asked to join to a specific room, you join him:
socket.on('room', function(room){
socket.join(room);
So far it's like the docs:
io.on('connection', function(socket){
socket.join('some room');
});
But your issue is with your emit, on each client connection, you listen to a message from your redis. Then you broadcast it to the room with an emit of the connected client.
Instead of that, you can do this:
io.on('connection', function(socket) {
socket.on('room', function(room){
socket.join(room);
});
socket.on('disconnect', function(){
console.log("disconnected!");
});
});
redis_client.on('message', function(channel, message) {
var myData = JSON.parse(message);
io.to('17').emit('cacad', 'u i u a a');
});
I think this happens on the socket-io-client side. not on the server-side. when I was using react-js for the client-side. I received the same message multiple times.
with the same server, I imported socket-io-client 4.4.1 in the vanilla js front-end project. then I didn't get multiple messages... :)
try use latest socket io client versions. i think they have fixed the issue in the latest versions..

Having problems sending private message in a socket.io room using redis

I'm trying to build a secure private facebook like messaging system using laravel, redis pub/sub and socket io. All the console.log functions log the messages to say everything went through on the node server and everything works fine untill I try and emit the message to the client. When I try to emit the message to the client nothing at all happens.
Although I don't think my controller method on laravel is of significance here it is anyway. You can skip the Laravel controller if it's not necessary
Laravel Message Controller:
public function store($id, Request $request)
{
//Stores message in $message
//Connects redis
$redis = Redis::connection();
$data = ['message' => $request->input('message'), 'user' => Auth::user()->name,
'room' => $message->conversation_id];
$redis->publish('message', json_encode($data));
return Redis::get('message');
response()->json([]);
}
Redis stuff being published in JSON output:
{message: 'some message', user: 'john doe', room: 1}
Node Server
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
server.listen(3000);
io.on('connection', function (socket) {
console.log("client connected");
var redisClient = redis.createClient();
redisClient.subscribe('message');
redisClient.on("message", function(channel, data) {
data = JSON.parse(data);
socket.join(data.room, function() {
console.log('Joined room '+data.room);
});
console.log("new message add in queue "+ data.room + " channel");
socket.to(data.room).emit(channel, data);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
Client Side JS
var socket = io.connect('http://localhost:3000');
socket.on('message', function (data) {
//Just console the message and user right now.
console.log(data.message+" " + data.user);
});
I don't know if my problem is that I'm not specifying the room on the client. If so is there any way of emitting the data to the client without specifying the room in the client side code? Why can't I emit the message to the client?

socket.io determine if a user is online or offline

We can trace if a connection is established or disconnected by this code
console.log('a user connected');
socket.on('disconnect', function () {
console.log('user disconnected');
});
Well, its fine. But how can we determine what user connected or gone offline. My client is written in PHP/HTML so they have a user ID.
If your clients have specific user IDs they need to send them to socket.io server. E.g. on client side you can do
// Browser (front-end)
<script>
const socket = io();
socket.emit('login',{userId:'YourUserID'});
</script>
And on server you will put something like
// server (back-end)
const users = {};
io.on('connection', function(socket){
console.log('a user connected');
socket.on('login', function(data){
console.log('a user ' + data.userId + ' connected');
// saving userId to object with socket ID
users[socket.id] = data.userId;
});
socket.on('disconnect', function(){
console.log('user ' + users[socket.id] + ' disconnected');
// remove saved socket from users object
delete users[socket.id];
});
});
Now you can pair socket ID to your user ID and work with it.
In addition of #galethil's answer, What if user opens more than one tab (socket connection), each tab (socket connection) has unique socket id for single user, so we need to manage array of socket ids for particular user,
Client Side Connection:
Support Socket IO Client v3.x,
<!-- SOCKET LIBRARY IN HTML -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.5/socket.io.js"></script>
const host = "http://yourdomain.com";
// PASS your query parameters
const queryParams = { userId: 123 };
const socket = io(host, {
path: "/pathToConnection",
transports: ['websocket'], // https://stackoverflow.com/a/52180905/8987128
upgrade: false,
query: queryParams,
reconnection: false,
rejectUnauthorized: false
});
socket.once("connect", () => {
// USER IS ONLINE
socket.on("online", (userId) => {
console.log(userId, "Is Online!"); // update online status
});
// USER IS OFFLINE
socket.on("offline", (userId) => {
console.log(userId, "Is Offline!"); // update offline status
});
});
Server Side Connection: Support Socket IO Server v3.x,
Dependencies:
const _ = require("lodash");
const express = require('express');
const app = express();
const port = 3000; // define your port
const server = app.listen(port, () => {
console.log(`We are Listening on port ${port}...`);
});
Connection:
const io = require('socket.io')(server, {
path: "/pathToConnection"
});
let users = {};
io.on('connection', (socket) => {
let userId = socket.handshake.query.userId; // GET USER ID
// CHECK IS USER EXHIST
if (!users[userId]) users[userId] = [];
// PUSH SOCKET ID FOR PARTICULAR USER ID
users[userId].push(socket.id);
// USER IS ONLINE BROAD CAST TO ALL CONNECTED USERS
io.sockets.emit("online", userId);
// DISCONNECT EVENT
socket.on('disconnect', (reason) => {
// REMOVE FROM SOCKET USERS
_.remove(users[userId], (u) => u === socket.id);
if (users[userId].length === 0) {
// ISER IS OFFLINE BROAD CAST TO ALL CONNECTED USERS
io.sockets.emit("offline", userId);
// REMOVE OBJECT
delete users[userId];
}
socket.disconnect(); // DISCONNECT SOCKET
});
});
GitHub Demo
We can identify the socket id in server who is connected and who is disconnected. So you can do something like this. You can use this setup if you have an identifier in client side
CLIENT
socket.emit('login', userId);
SERVER SIDE
const users = {};
io.on("connection", (socket) => {
socket.on("login", (data) => {
users[socket.id] = data;
});
socket.on("disconnecting", (reason) => {
delete users[socket.id]; // remove the user. -- maybe not the exact code
});
});
Hope you get the idea.

Socket.io-client does not receive any messages after successful connection

I have a working socket.io server up and running, and i am trying to implement a server side socket.io client. Below is the code snippet i have been using for testing. The problem with this is that the client outputs the message only once, in this case it receives 'Welcome' only. I have tried sending messages to the private channel, 'message' via browser but it doesn't show any output even though the server can receive and emit the message successfully.
Client
var io = require('socket.io-client');
var socket = io.connect('http://localhost:3000', {'force new connection': true});
socket.on('connect', function(){
socket.on('message', function (data) {
console.log(data);
});
});
Server
var io = require('socket.io').listen(server);
var i=0;
io.sockets.on('connection', function (socket) {
socket.emit('message', { 'msg': 'Welcome'});
socket.on('message', function (from, msg) {
socket.emit('message', { 'msg': 'Hello World - ' + i });
i++;
});
});
Have you tried doing this?
console.log(data.msg);
Can you try changing "socket" to "this":
this.emit('message', { 'msg': 'Hello World - ' + i });
You should emit from client side to server. So server can send the data back to client. I guess this code works fine :-)
Client
var io = require('socket.io-client');
var socket = io.connect('http://localhost:3000', {'force new connection': true});
socket.on('connect', function(){
socket.on('messageRecieved', function (data) {
console.log(data);
});
socket.emit('message','some message');
});
Server
var io = require('socket.io').listen(server);
var i=0;
io.sockets.on('connection', function (socket) {
socket.on('message', function (msg) {
console.log(msg);
socket.emit('messageRecieved', { 'msg': 'Hello World - ' + i });
i++;
});
});

Resources