I am trying to make a chat app which sends first message as "Hi. there".
But due to some some reasons (unstable internet connection might be one) the socket get initialized multiple times and sends the "Hi. there" message multiple times. Below is the code. How to stop the app for sending multiple messages?
io.socket.on('connect', function() {
/* On successfull connection to server */
console.log('Connected to server');
//Some code here
io.socket.get(url + '/userstatus/subscribe', function(resData, jwres) {
//Some code here
io.socket.on("userstatus", function(event) {
//Socket updartes
// Send Message code at this line.
}
}
});
You need to change your client side code, so that it stores state, and sends it to the server on reconnect. That way the server can give the correct response.
Something like this might work:
socket.on('connect', function() {
/* On successfull connection to server */
console.log('Connected to server');
socket.emit('state', state_object);
});
Related
So I have set up a socket connection for a chat app. Under normal circumstances where both the sender and receiver are connected to the internet, the message sent between either of them passing through my NodeJS server reach's them. But if one of them is offline and a new message is sent to them, the server will send it to the user but, since the user is offline, won't accept them at that point in time. But once the user gets back online, he should be able to accept that message. How do I make this work?
Nodejs server code
io.on("connection", (socket) => {
console.log("Connected to socket io");
socket.on('setupConnection',(userData)=>{
socket.join(userData.id);
});
socket.on("newMessage", (chatData) => {
const { message,to } = chatData;
socket.in(to).emit("newMessage", { msg: message });
});
})
I am trying to use websocket.io with nodejs and angular. I am trying to build a one-to-one chat application. Here is snippets of my code:
server.js
app.io.on('connection', function(socket){
console.info(`Client connected [id=${socket.id}]`);
socket.on('disconnect', function(){
console.info(`Client gone [id=${socket.id}]`);
});
});
sendmessage.js
router.post("/auth/sendMessage", function(req, res) {
//rest api to handle send message
//mongodb insert
app.io.emit('new-message', { message: message});
}
Angular Client
this.socket.on("new-message", function(data) {
if (
data.message.conversationId === self.conversationId &&
data.message.sender === "customer"
) {
self.messages.push(data.message);
setTimeout(function() {
self.messagesDiv.nativeElement.scrollTop =
self.messagesDiv.nativeElement.scrollHeight;
}, 100);
}
});
Now, the problem that I am facing is new-message will send message to all the listeners. Although, I am handling the logic on the client side, to only show the message if it is sent by specific conversationId, this should be handled at the server end only due to security issues.
So, I want to be able to send to specific users only. I think this can somehow be done using socket.id which would be unique for each connection. But how can I pass this socket.id from client to server, so that server knows on which client it needs to send the data?
There are two things here, app.io and socket. In the first snippet, you use app.io.on('connection', function(socket){. This socket is the new connection. You can store this socket object somewhere in the database or in memory.
Now, app.io.emit will send the message to all the clients, while this socket that you stored somewhere will send the message to that particular client/user on socket.emit.
In short, you need to do
router.post("/auth/sendMessage", function(req, res) {
//rest api to handle send message
//mongodb insert
socket.emit('new-message', { message: message});
}
Here is a small tic-tac-toe game I made using sockets. It will give you more insight on how to use sockets. This is not perfect but you will still understand how to use sockets.
tl;dr save socket from app.io.on('connection'... and use socket.emit to send messages to that particular client.
I'm starting to work with Socket.io and my nodeJS API
I succeeded to get my user connected, and showed a message on my server.
But now, I'm trying to send data to my client -> then server -> then client again etc.
But when I use emit nothing appends... So this i my code :
SERVER SIDE
io.on('connection', function(socket){
console.log("user connected") // I see that
socket.emit('text', 'it works!'); //
socket.on('test1', function (data) {
console.log('received 1 : '); // Never showed
console.log(data); // Never showed
});
}
CLIENT SIDE
var socket = io.connect(myUrl); // good connection
socket.emit ('test1', {map: 4, coords: '0.0'}); // never showed on the server side
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
Any ideas?
thanks !
Your Starter Code seems to be valid, you need to check two things :
if you successfully included the socket.min.js in the client side
if you re having any error printed in the console
On the client side, you have to wait until the connection succeeds before it is safe to send data to the server. Connecting to the server is not synchronous or instantaneous (thus it is not ready immediately). You are trying to send data before the connection is ready.
Put your first send of data inside a socket.on('connect', ...) handler.
var socket = io.connect(myUrl); // good connection
// send some data as soon as we are connected
socket.on('connect', function() {
socket.emit ('test1', {map: 4, coords: '0.0'});
});
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
this worked for me
CLIENT SIDE
//sending custom data to server after successful connection
socket.on('connect', function(){
this.socket.emit('client-to-server', {map: 4, coords: '0.0'});
});
//listening the event fired by the socket server
socket.on('server-to-client', function(dataSendbyTheServer){
// do whatever you want
console.log(dataSendbyTheServer);
});
SERVER SIDE
io.on('connection', function(socket) {
// listening the event fired by the client
socket.on('client-to-server', function (data) {
console.log('received 1 : ');
// sending back to client
io.emit('server-to-client', data)
});
});
I am still learning node.js basics. My flow is like this,
browser<-->node<-->backend server doing calculation.
node and backend uses socket to communicate.
From the browser there are start/stop buttons to ask backend to start/stop the
calculation.
When node asks backend to start/stop, it must query to see if backend is
alive first.
My code is like this -
app.get('/stopCmd', function(req, res)
{
socketToBackendServer.write("status", function() {
console.log("Sending:", 'Node asking for STATUS');
});
socketToBackendServer.on("data", function() {
if(status is ok) // pseudo code
{
socketToBackendServer.write("stop", function() {
console.log("Sending:", 'Node sending STOP');
});
} else {
console.log("backend server is NOT ready");
}
});
});
app.get('/startCmd', function(req, res)
{
// do similar things as stopCmd
});
/////////////////////////////////////////////////
var socketToBackendServer = net.connect(2899);
function openSocket() {
socketToBackendServer.setKeepAlive(true);
socketToBackendServer.on('connect', onConnect.bind({}, socketToBackendServer));
socketToBackendServer.on('error', onError.bind({}, socketToBackendServer));
}
function onConnect(socket) {
var myData;
console.log('Socket is open!');
socket.on('data', function(data) {
console.log('Received:', data);
io.emit('time', { time: data.toJSON() });
});
}
function onError(socket) {
console.log('Socket error!');
// Kill socket
clearInterval(interval);
socket.destroy();
socket.unref();
// Re-open socket
setTimeout(openSocket, 1e3);
}
openSocket();
server.listen(7778);
if using the same browser, if i go crazy clicking start/stop... for the "
stopCmd", how to make sure when it queries "status", the response is caught
by its function, not "startCmd"'s ?
it's this line
socketToBackendServer.on("data", function()
Thank you again !
You can use multiple connections to the backend server, so one function can freely use one channel, the responses won't mix.
Or you can use a multiplexer function, that you call from both of your functions:
It could work if you can identify your requests, like you send and id with the status, for example socketToBackendServer.write("status 1", ... , and you send the id with the status response back from the backend server (if it yours). In this way you can send multiple requests at the same time, and when the response come, you can identify it, and call the callback function that you stored in an array with the ids.
You only send one request, and you wait for the response before you send another one. You must use a waiting queue, where you store the request, and the callback functions.
I have been trying to disconnect from a namespace or even from the main socket connection itself but have been failing. Below is my code
Server Side:
socket.on('userDisconnect', function () {
socket.disconnect();
console.log("User Disconnected");
});
Client Side:
// already connected to /world namespace
socket.emit('userDisconnect');
socket.disconnect();
socket = io.connect('http://something/india' );
I tried disconnecting from both client and serve side but it doesnt work. Can anyone point out the mistake.
This is what is been written to console by socket.io
info - booting client
debug - websocket writing 0::/world
User Disconnected
debug - client authorized for /india
debug - websocket writing 1::/india
/world is the namespace its trying to disconnect from and then its trying to connect to /india namespace.
This worked for me
broadcastSocket.packet({ type: 'disconnect' });
broadcastSocket.$emit('disconnect');
disconnectNamespace(broadcastSocket.name, broadcastSocket.socket);
function disconnectNamespace (name,socket) {
if (socket.namespaces[name]) {
var nsp = socket.of(name);
nsp.packet({ type: 'disconnect' });
nsp.$emit('disconnect');
delete socket.namespaces[name];
if (Object.keys(socket.namespaces).length === 0) {
socket.disconnect();
}
}
};
For socket.io v.1.3.2
Create with:
sio = io('ws://localhost:13000/device');
Delete with:
sio.disconnect();
delete sio.io.nsps[sio.nsp]; // sio.nsp = '/device'
delete sio;
This worked for me.
On the server
nsp.on('connection', (socket) => {
setTimeout(() => {
socket.disconnect(false)
}, 5000);
});
Disconnects this client. If the value of close is true, closes the underlying connection. Otherwise, it just disconnects the namespace. It's in the documentation https://socket.io/docs/server-api/
It doesn't look like you told the client to wait for disconnect before reconnecting.
// already connected to /world namespace
socket.emit('userDisconnect');
socket.on('disconnect', function () {
socket = io.connect('http://something/india');
// stuff with india socket
});
Use disconnect() method on the server or on the client (or both like your did in your example). When you first connect to the server, add 'forceNew':false to the client connect method, something like this:
var socket = io('http://localhost:3001', {'forceNew':false});