Socket.io ID issue, wrong ID

let start by saying I'm not a programmer and I only learned nodeJS, Jquery, AJAX, Socket.IO two days ago. As in, i had no knowledge of them at all.

I'm trying to create a jackbox-like system and got as far as creating rooms and adding players. But something is going wrong with the socket.id, it's always returning the same ID for each player I add. this is the code that runs into the issue (Note: room creating is called by unity and that seems to be working perfectly, because the roomcodes and id is stored exactly like they should):

var rooms = [];


//Check if socket is connected
io.on('connection',function(socket){
    console.log('made socket connection:'+socket.id);


      //if submit button is pressed on the login form
      app.post('/button', urlencodedParser, function(req, res){
      //check if a roomcode exists with the entered roomcode
      var found = rooms.some(el => el.roomcode === req.body.room);
      //if it exists
      if (found){
        //find the index in the room array of that room
        var targetindex = rooms.findIndex(element => element.roomcode === req.body.room);
        //send a message to that room in unity that you want to join
        io.to(rooms[targetindex].gamesocketid).emit('joinroom', {player: req.body.player, room: req.body.room, socket: socket.id});
        //add the player to the players array of that room
        rooms[targetindex].players.push({nickname: req.body.player, id: socket.id});
        //log the addition of the player to the console
        console.log('player ' + req.body.player + ' joined room ' + req.body.room + ' with socket ID ' + socket.id);
        //Log the room itself to the console
        console.log(rooms[targetindex]);
        //send a response with the data. to tell you successfully added the player to ajax
        res.json(rooms[targetindex]);
      } else {
        console.log('room not found');
      }
    });



    socket.on('createroom',function(data){
      JSON.stringify(data);
      console.log('Game with socket id ' + socket.id + ' created a room with room code ' + data.roomcode );
      var players = [];
      rooms.push({roomcode: data.roomcode, gamesocketid: socket.id, players: players});
      console.log(rooms);
      //console.log('room code ' + RoomJSON.roomcode);
    });

    socket.on('destroyroom',function(data){
      JSON.stringify(data);
      console.log('Destroy a room with room code ' + data.roomcode );
      rooms = rooms.filter(function(value){
        return value.roomcode !== data.roomcode;
      });
    });


});

I am pretty sure, I'm probably doing something that is not allowed. I thought it might be related on trying to run app.post from within the io.on('connection' , if that is the case I'm kind of lost on how to solve it. I need the socket.id of the player stored in my array, so I can later use those ID's to send important game data.

My Console Log (note in this log all ID's are the same, but that isn't always the case):

    PS D:\nodejs\Projects\ZoomFriends> nodemon app
[nodemon] 2.0.3
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
made socket connection:Fe9o3x5-_e1osj5sAAAA
Game with socket id Fe9o3x5-_e1osj5sAAAA created a room with room code JBYK
[
  {
    roomcode: 'JBYK',
    gamesocketid: 'Fe9o3x5-_e1osj5sAAAA',
    players: []

  }
]
made socket connection:6sjC6WMGyky2G5-sAAAB
Fe9o3x5-_e1osj5sAAAA
player Sebastiaan Phone joined room JBYK with socket ID Fe9o3x5-_e1osj5sAAAA
{
  roomcode: 'JBYK',
  gamesocketid: 'Fe9o3x5-_e1osj5sAAAA',
  players: [ { nickname: 'Sebastiaan Phone', id: 'Fe9o3x5-_e1osj5sAAAA' } ]
}
made socket connection:sZFzMaIow5TVCf4dAAAC
Fe9o3x5-_e1osj5sAAAA
player Sebastiaan Browser joined room JBYK with socket ID Fe9o3x5-_e1osj5sAAAA
{
  roomcode: 'JBYK',
  gamesocketid: 'Fe9o3x5-_e1osj5sAAAA',
  players: [
    { nickname: 'Sebastiaan Phone', id: 'Fe9o3x5-_e1osj5sAAAA' },
    { nickname: 'Sebastiaan Browser', id: 'Fe9o3x5-_e1osj5sAAAA' }
  ]
}

For completionists sake, I will add the other sides: app.js:

//Set up express
var express = require('express');

//Set up socket.io
var socket = require('socket.io')//({transports: ['websocket'],});

//create an express app to talk to
var app = express();

//Include the controller
var zoomFriendsController = require('./controllers/zoomFriendsController');

//set up view-template engine
app.set('view engine', 'ejs');

//allow static files
app.use(express.static('./public'));

//listen to a port and start the server
var server = app.listen(4000);
console.log('listening to port 4000');

// Socket Setup
var io = socket(server);

//fire the controller
zoomFriendsController(app,io);

rooms.ejs

<!DOCTYPE html>
<html>
  <head>
    <title>Todo List</title>
    <script
      src="https://code.jquery.com/jquery-3.5.0.min.js"
      integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ="
      crossorigin="anonymous"></script>
    <link href="/assets/styles.css" rel="stylesheet" type="text/css" />
    <script src="/assets/zoomFriendsAjax.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
  </head>
  <body>
    <script src="/assets/sockets.js"></script>
    <h2>Welcome To ZoomFriends</h2>

    <div id="pagecontent">
      <div id="serverform">
        <form>
          <label for="servercode"><strong>Server Code:</strong></label>
          <input type="text" id="servercodeinput" name="servercode" placeholder="Insert your server code here..." required>
          <label for="nickname"><strong>Your Nickname</strong></label>
          <input type="text" id="nickname" name="nickname" placeholder="Insert your nickname here..." required>
          <button type=submit>join room</button>
        </form>
      </div>
      <div id="connpage">
        <h2>Connected to server</h2>
        <button id=startgame>Start Game if all players have joined!</button>
      </div>
      <div id="gamepage">
        <h2>Game is Started</h2>
      </div>
    </div>
  </body>
</html>

zoomFriendsAjax.js

$(document).ready(function(){


  $('#serverform').on('submit', function(){

      var player = $('input[type="text"]#nickname');
      var room = $('input[type="text"]#servercodeinput');
      var joindata = {player: player.val(), room: room.val().toUpperCase()};

      $.ajax({
        type: 'POST',
        url: '/button',
        data: joindata,
        success: function(data){
          //do something with the data via front-end framework
          //location.reload();
          //alert('button pressed');

          serverconnected();

        }
      });




      return false;

  });

  $('#startgame').on('click', function(){
    //alert('button pressed');
    var started = true;

    $.ajax({
      type: 'POST',
      url: '/start',
      data: started,
      success: function(data){
        //do something with the data via front-end framework
        //location.reload();
        gamestarted();

      }
    });

    return false;
  });

  function serverconnected(){
    $('#connpage').show();
    $('#serverform').hide();
  }

  function gamestarted(){
    alert('gamestarted function happening');
    $('#gamepage').show();
    $('#connpage').hide();
  }

  function nosuchroom(){
    alert('Wrong Room Name');
  }

});

styles.css

body{
    background: #0d1521;
    font-family: tahoma;
    color: #989898;
    text-align: center;
}

#todo-table{
    position: relative;
    width: 95%;
    background: #090d13;
    margin: 0 auto;
    padding: 20px;
    box-sizing: border-box;
}

#todo-table form:after{
    margin: 0;
    content: '';
    display: block;
    clear: both;
}

#connpage{
    display: none;
}

#gamepage{
    display: none;
}
#servercodeinput{
    text-transform: uppercase;
}

input::placeholder {
  font-style: italic;
}

input[type="text"]{
    width: 100%;
    padding: 20px;
    background:#181c22;
    border: 0;
    float: left;
    font-size: 20px;
    color: #989898;
    text-align: center;
}

label{
    width: 100%;
    padding: 20px;
    background:#23282e;
    border: 0;
    float: left;
    font-size: 20px;
    color: #989898;
    text-align: center;
}

button{
    padding: 20px;
    width: 100%;
    float: left;
    background: #23282e;
    border: 0;
    box-sizing: border-box;
    color: #fff;
    cursor: pointer;
    font-size: 80px;
}

ul{
    list-style-type: none;
    padding: 0;
    margin: 0;
}

li{
    width: 100%;
    padding: 20px;
    box-sizing: border-box;
    font-family: arial;
    font-size: 20px;
    cursor: pointer;
    letter-spacing: 1px;
}

li:hover{
    text-decoration: line-through;
    background: rgba(0,0,0,0.2);
}

h1{
    background: url(/assets/logo.png) no-repeat center;
    margin-bottom: 0;
    text-indent: -10000px;
    text-align: center;
}

sockets.js

//make connection
var socket = io.connect('95.97.158.61:4000');

and finally the full ZoomFriendsController.js:

var bodyParser = require('body-parser');
var mongoose = require('mongoose');

//Connect to database
mongoose.connect('mongodb+srv://SebastiaanVW:[email protected]/test?retryWrites=true&w=majority', { useNewUrlParser: true , useUnifiedTopology: true })

//Create a schema - this is a blueprint
var roomSchema = new mongoose.Schema({
  room: String
  //players: Array
});

//create a model
var Rooms = mongoose.model('Room', roomSchema)

var urlencodedParser = bodyParser.urlencoded({extended: false});

//Start Functions
module.exports = function(app,io){

var rooms = [];
var myroomindex = -1;

//Check if socket is connected
io.on('connection',function(socket){
    console.log('made socket connection:'+socket.id);


      //if submit button is pressed on the login form
      app.post('/button', urlencodedParser, function(req, res){
      console.log(socket.id);
      //put the player data in message variable
      //var message = req.body.player;
      //check if a roomcode exists with the entered roomcode
      var found = rooms.some(el => el.roomcode === req.body.room);
      //if it exists
      if (found){
        //find the index in the room array of that room
        var targetindex = rooms.findIndex(element => element.roomcode === req.body.room);
        //send a message to that room in unity that you want to join
        io.to(rooms[targetindex].gamesocketid).emit('joinroom', {player: req.body.player, room: req.body.room, socket: socket.id});
        //add the player to the players array of that room
        rooms[targetindex].players.push({nickname: req.body.player, id: socket.id});
        //log the addition of the player to the console
        console.log('player ' + req.body.player + ' joined room ' + req.body.room + ' with socket ID ' + socket.id);
        //Log the room itself to the console
        console.log(rooms[targetindex]);
        //send a response with the data. to tell you successfully added the player to ajax
        res.json(rooms[targetindex]);
      } else {
        console.log('room not found');
        res.json(rooms[targetindex]);
      }
    });

    //if submit is pressed on the startgame button
    app.post('/start', urlencodedParser, function(req, res){
        console.log('game started');
        var goingwell = true;
        io.to(rooms[myroomindex].gamesocketid).emit('gamestarted',{started: true});
        rooms[myroomindex].players.forEach(function(item,i){
          var tempsocket = rooms[myroomindex].players[i].socket
          console.log(tempsocket);
          io.to(tempsocket).emit('gamestarted',{started: true});
        });
        res.json(goingwell);
    });

    socket.on('createroom',function(data){
      JSON.stringify(data);
      console.log('Game with socket id ' + socket.id + ' created a room with room code ' + data.roomcode );
      var players = [];
      rooms.push({roomcode: data.roomcode, gamesocketid: socket.id, players: players});
      console.log(rooms);
      //console.log('room code ' + RoomJSON.roomcode);
    });

    socket.on('destroyroom',function(data){
      JSON.stringify(data);
      console.log('Destroy a room with room code ' + data.roomcode );
      rooms = rooms.filter(function(value){
        return value.roomcode !== data.roomcode;
      });
    });

    socket.on('gamestarted',function(data){
        //res.render('gamestarted');
        console.log('recieved gamestarted');
    });
});



app.get('/', function(req, res){
  res.render('rooms');
});

};

I know there is lots of stuff in there I'm not using yet and also some stuff that won't work, like the myroomindex value. But for now I need to solve the socketid issue. Basically all my players are getting the same socket ID in my array. Thanks for taking a look!

Upvotes: 1

Views: 456

Answers (1)

jfriend00
jfriend00

Reputation: 707328

You can't put app.post('/button', ...) inside io.on('connection', ...). Can't architect it that way. This means that every time you get a new socket.io connection, you add an additional duplicate app.post() handler. Then, anytime that route gets hit, they ALL will compete for the route and only the first one that was installed will win and thus it will always be using the first socket.id that ever connected no matter which client send the POST request.

You have to remember that app.xxx() register routes for ALL users and they are permanent for the life of your server. They are not just for the user whose just connected with socket.io.

Instead, you need to move the app.post() outside of the io.on('connection, ...) and here are some options:

  1. Send the socket.id from the client with the POST data (not particularly desirable because it can be spoofed).
  2. Get it from the socket.io cookie (if you can).
  3. Save it yourself in a cookie when the socket.io connection connects and then you can get it from that cookie when you get the app.post()
  4. Don't use a form post. Just send the data in a socket.io message and then you will already know which socket it is.

My favorite is probably #4.

Upvotes: 1

Related Questions