1

I'm facing a problem with socket.io and node js.

Context

I have two servers, one of them is processing heavy jobs and the other is responding to the clients. The main case is the following one :

  1. The client request data
  2. The "mid server" looks if I have this data in the database. If I haven't, itsend a request to the second server
  3. The second server performs the research.
  4. Once its done, the second server push de data to the "mid server"
  5. The mid server finally push the data to the client (and persists it for future client requests)

Here's the sample code

Client

<script type="text/javascript"/>
    var socket = io('https://localhost:9091', {'forceNew': true);
    // send a request to the mid server
    socket.emit('request', data);

    socket.on('response', async (response) => {
        // when the mid server responds, the response is printed
        $('#container').append(response);
    });
</script>

Mid server

const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

// in order to use this server as a Socket.io client
const secondServer = require('socket.io-client').connect('http://localhost:9092');

app.set('view engine', 'ejs');

app.get('/', (req, res) => {
    res.render('index', {})
});

io.on('connection', async (socket) => {

    console.log('User connected');

    // On client request
    socket.on('request', async (data) => {

        console.log('Requesting from ' + socket.id);

        // The same request is transmited to the second server
        secondServer.emit('request', data);
    });

    // Once the second server has finished his job
    secondServer.on('response', async (data) => {

        console.log('Responding for ' + socket.id);

        // I send the data back to the client
        socket.emit('response', data);
    });

    socket.on('disconnect', () => {
        socket.disconnect();
    });
});

// port is 9091
http.listen(port, () => {
    console.log('Server listening on port ' + port);
});

Second server

const io = require("socket.io").listen(9092);

io.on("connection", function (socket) {

    socket.on('request', async () => {
        // await in order to wait the heavyJob to be done before sending the response
        var data = await heavyJob()

        // Send back the data to the mid server
        socket.emit('response', data);

    });
});

Problem

The problem I'm facing is, if I refresh the client page, the mid server will send twice the data, once to the old socket and the once for the new one as so :

console output

I have also tried to respond to the client with socket.emit('response', data) on mid server side and socket.on('response', (data) => {}) on client side instead of using callback function. It doesn't change anything.

Do I misunderstanding something ?

Thanks for your help

Edit

It doesn't only happen when the client is refreshing his page. It happens when two different clients send a request at the same time. The server is responding four times, two times for each client.

console output

NicoTine
  • 51
  • 3
  • 12

1 Answers1

1

You are right Nico, I didn't recognized callback can't be reached. It was my mistake.

According to your edited code, you can pull out "secondServer.on('response'.." from "io.on('connection'"'s callback.

You can try below and I hope this would be helpful.

Mid Server

io.on('connection', async (socket) => {

    console.log('User connected');

    // On client request
    socket.on('request', async (data) => {

        console.log('Requesting from ' + socket.id);

        // The same request is transmited to the second server
        // give data and socket.id to secondServer.
        secondServer.emit('request', {data:data, id:socket.id});
    });

    // Once the second server has finished his job
    socket.on('disconnect', () => {
        socket.disconnect();
    });
});

secondServer.on('response', async (reply) => {
    const {id, data} = reply;
    console.log('Responding for ' + id);
    // I send the data back to the client
    io.to(id).emit('response', data);
});

Second Server

const io = require("socket.io").listen(9092);

io.on("connection", function (socket) {

    socket.on('request', async (req) => {
        // await in order to wait the heavyJob to be done before sending the response
        const {id} = req; 
        var data = await heavyJob();
        const reply = { id, data };
        // Send back the data to the mid server
        socket.emit('response', reply);

    });
});

I think you need pull out "secondServer.on('response'.." code from "socket.on('request',..." callback.

io.on('connection', async (socket) => {

    console.log('User connected');
    // On client request
    socket.on('request', async (data, callback) => {

        console.log('Requesting from ' + socket.id);
        // The same request is transmited to the second server
        secondServer.emit('request', data);
    });
    secondServer.on('response', async (data) => {
            console.log('Responding for ' + socket.id);
            callback(data.images);
    });  
});
ryuken73
  • 763
  • 5
  • 13
  • I tried that as well. It doesn't change anything. Note that `callback` will not work anymore since its a parameter of function "socket.on('...')". I edit my question to update my code – NicoTine Oct 05 '19 at 13:33
  • It's working now with your solution ! Thanks a lot ! – NicoTine Oct 06 '19 at 19:14