How can i detect if a message did not reach my node.js+socket.io server. I have an emit from the server for message sent success.
socket.on('message', function(msg) {
var sendersusername = msg.source;
if (io.sockets.sockets[socket.id] != undefined)
{
io.sockets.sockets[socket.id].emit('messagesentsuccess',
{"user": msg.target,
"message":msg.message
});
}
});
from this code i get a success message when a message reaches the server. How do i know if the message could not be sent to the server?
you can use
socket.on('error', function (err) {
console.log(err);
});
to detect errors`
Related
I am setting up a web socket server with socket.io and it seems like that messages are sent at least twice. Sometimes even trice. (very rarely even 4+ times) They are never sent once though. How should I setup my handlers or my client code so every message is received exactly once all the time?
My client is in swift and my server in node.js. I am running Ubuntu 16.04 on the server itself.
Node.js:
// Here is an array of all connections to the server
var connections = {};
io.sockets.on('connection', newConnection);
function newConnection(socket) {
socket.on('add-user', function(user) {
connections[user.id] = {
"socket": socket.id
};
});
socket.on('chat-message', function(message) {
console.log(message);
if (connections[message.receiver]) {
console.log("Send to: " + connections[message.receiver].socket);
// Here are some varients of the emit command. Seems like they all do the same
//io.sockets.connected[connections[message.receiver].socket].emit("chat-message", message);
//io.to(connections[message.receiver].socket).emit("chat-message", message);
socket.broadcast.to(connections[message.receiver].socket).emit("chat-message", message);
} else {
console.log("Send push notification")
}
});
//Removing the socket on disconnect
socket.on('disconnect', function() {
console.log("The client disconnected");
for (var id in connections) {
if (connections[id].socket === socket.id) {
delete connections[id];
}
}
})
}
The "console.log(message);" in the messages handler is only called once. That's the confusing part for me. If the handler is called twice, why is this only printed once? Still, on the handler in my swift code, the handler for received messages is called multiple times.
im using socket.io with sticky session (https://github.com/indutny/sticky-session). I have a little chat application and always when im using 2 or more sockets on one one machine the socket.on(...) event listener is firing very very slow. When i'm using only one socket-connection for each cluster everything works fine and fast. What could be the cause. Could it be because of sticky session?
Edit:
This is the socket- connect function (of my worker - clusters):
WebSockets.on('connect', function (socket) {
console.log(`${process.pid}`);
//send data example: socket.emit('news', {a: "b"});
//TODO: implement switch case that validates which chat type it is.
//TODO: why is the event so slow when using 2 connections?: https://socketio.slack.com/messages/C02AS4S1H/
socket.on('chat message', function (msg) {
console.log("sending message: " + msg)
try {
//send the message to all other cluster-workers:
process.send({ chat_message: msg });
} catch (e) { }
});
//if the cluster gets a message then he sends it to the user, if its the correct user
function message_handler(msg) {
try {
//TODO: send message only to the correct users
if (msg != null && msg.chat_message != null) {
WebSockets.emit('chat message', msg.chat_message);
}
} catch (e) { }
}
process.on('message', message_handler);
//When the socket disconnects:
socket.on('disconnect', function(reason) {
//remove the event listener:
process.removeListener('message', message_handler);
});
});
Explanation: I'm sending all the data i get from the socket to all the other clusters. Then I catch them with:
process.on('message', message_handler);
To send incomming chat messages.
I created the Clusters with sticky session like in the example (https://github.com/indutny/sticky-session)
I'm trying to send news to my client. On connect, it works great, but for some reason on broadcast2 it wont get any response client sided, even know its the same piece of code, and even that broadcast2's console.log is working.
Q: How can i make sure broadcast2 emit will work?
This works:
socket.on('message', function (data) {
console.log('message gotten');
socket.emit('news', { message: 'xxxx' });
});
this wont work:
socket.on('broadcast2', function (data) {
console.log("broadcast revieced");
socket.emit('news', { message: 'xxxx' });
});
this is node.js response:
total code in node.js
socket.on('message', function (data) {
console.log('message gotten');
});
socket.on('another-message', function (data) {
socket.emit('not-news', { hello: 'world' });
});
socket.on('broadcast2', function (data) {
console.log("broadcast revieced");
socket.emit('news', { message: 'xxxx' });
});
and this on the client side:
var socket = io.connect('mysite:8080');
function sender() {
console.log('sending tester');
socket.emit('sendertester', 2);
}
socket.on('connect',function(){
});
socket.on('tester', function(msg){
console.log("callback");
});
socket.on('news', function(message) {
console.log("INCOMMING NEWS");
console.log(message);
});
UPDATE 1:
The broadcast2 socket, sent by PHP:
function broadcast($message,$broadcast = 'broadcast2') {
$client = new Client(new Version1X('myurlhidden:8080'));
$client->initialize();
$client->emit($broadcast, ['message' => $message]);
$client->close();
}
UPDATE 2:
**Question two: Cause my broadcast2 is sent before the client sided is loaded, and then the client connects to the node, could that be the cause?
But in the same time, im already preloading the class that holds the broadcast2 emitter.
Using codeigniter framework.**
UPDATE 3
I was trying to check my theory on update 2, by having two users logged in, while user one trying to perform the trigger. user two gets no output, so i suppose that theory is busted.
The server cannot send a message to any socket before it is connected. You have to wait until you have something listening to receive what you are sending.
I wouldn't call close after the emit either, as you may close the connection before the client has received the message, emit doesn't wait for the client to receive the data before returning its asynchronous.
Instead let the clients close the connections when they terminate.
I have set up sockets on my client and server, but I can't seem to get my data to come into my client. It seems they are connecting properly, I just can't get any data to come through. There are no error messages either.
Here is my server code:
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('custom-message', function () {
console.log("Hitting messages socket");
Message.find(function(err, messages){
if(err){
socket.emit('custom-message', err)
} else {
socket.emit('custom-message', messages);
}
})
});
});
Here is the function in the client that connects to the socket:
loadMessagesFromServer: function(){
console.log("About to load messages")
socket.on('custom-message', function(msg){
console.log("connected in client", msg)
});
},
Like I said it is a pretty simple example, I just can't seem to get the data in loadMessagesFromServer .. And there are no erros, the only way I have been debugging is trying different things..
You are listening on the event messages. So you need to emit the same event not socket.emit('messages: err', err). Try with socket.emit("messages", error). Moreover, in your server-side code, you need first to receive a message event and only then your socket will emit the messages. Remove the socket.on(custom-messages). Why do you need it?
Server-side code
io.on('connection', function (socket) {
/* Here a client connection is established. The on("connection")
* event will be triggered as many times as`io.connect("the-uri")`
* is triggered (and succeeded) in the client`
*/
// Listening for the post event
socket.on("post", function(messages){
console.log("client posted data:", messages)
// Find messages and emit result
Message.find(function(err, messages){
if(err){
socket.emit('error', err)
} else {
socket.emit("message", messages);
}
});
});
});
Client-side code
registerOnMessageFromServerListener: function(){
socket.on("message", function(msg){
console.log("received message:", msg);
});
registerOnErrorFromServerListener: function(){
socket.on("error", function(error){
console.log("an error occured:", error);
});
registerOnMessageFromServerListener();
registerOnErrorFromServerListener();
socket.emit("post", "a-message");
Also make sure that you call the loadMessagesFromServer before you establish the socket connection
I have yet to figure out how to directly respond to only the sender using socket.io
I have learned that io.sockets.emit sends to all clients but I wont to send information back to the sender.
code:
socket.on('login', function (data) {
db.users.find({username: cc.lowerCase(data.username)}, function(err, users) {
if (users.length > 0) {
users.forEach( function(user) {
console.log(user.length);
if (user.password == data.password) {
io.sockets.emit('login', { username: user.username });
} else {
io.sockets.emit('error', { message: "Wrong username or password!" });
}
});
} else {
io.sockets.emit('error', { message: "Wrong username or password!" });
}
});
});
When your server listens, you usually get a socket at the "connection" event :
require('socket.io').on('connect', function(socket){
A socket connects 2 points : the client and the server. When you emit on this socket, you emit to this specific client.
Example :
var io = require('socket.io');
io.on('connect', function(socket){
socket.on('A', function(something){
// we just received a message
// let's respond to *that* client :
socket.emit('B', somethingElse);
});
});
Be careful that those are two different calls :
socket.emit : emit to just one socket
io.sockets.emit : emit to all sockets
Simple example
The syntax is confusing in socketio. Also, every socket is automatically connected to their own room with the id socket.id (this is how private chat works in socketio, they use rooms).
Send to the sender and noone else
socket.emit('hello', msg);
Send to everyone including the sender(if the sender is in the room) in the room "my room"
io.to('my room').emit('hello', msg);
Send to everyone except the sender(if the sender is in the room) in the room "my room"
socket.broadcast.to('my room').emit('hello', msg);
Send to everyone in every room, including the sender
io.emit('hello', msg); // short version
io.sockets.emit('hello', msg);
Send to specific socket only (private chat)
socket.broadcast.to(otherSocket.id).emit('hello', msg);
late but better than never ;)
I had smth like this:
io.on('connection', function(socket){
socket.emit('some event', data);
socket.on('private event', function(message){
this.emit('other private event', message);
}
}
After some testing, I realized that 'this.emit' inside 'private event' closure send back only to sender. So i tried 'this.broadcast.emit', which send the message to all connected except the sender. I believe this is what you want from your code.