5

I'm using socket.io and socket.io-client on the Express and React sides, respectively.

On the server side, I console.log in the connection event with the socket.id, and it always displays two connections when I only have one page open, like so:

A user connected woF_Gu_8ElqMB7a5AAAC A user connected lBAycJ6j0X5Q469SAAAD

However, when emitting messages from the front end, only one connection is used.

Here's how I set up socket.io server side:

// ** bin/www file **
var server = http.createServer(app);
const io = require('socket.io')(server);

// Get socket module and pass it the io socket from here
require('../sockets')(io);

// ** sockets.js **
module.exports = io => {
  io.on('connection', (socket) => {
    console.log("A user connected", socket.id); // Fires twice with different IDs

    socket.on("Setup", data => {
      console.log("Data received:", data); // Only fires once per emit from frontend
    }

    socket.on("disconnect", () => {
      console.log("User disconnected");
    }

}

Here's how I set up client side, though I'm not sure this matters since it's happening consistently even when I don't have this code in:

import io from 'socket.io-client';
const socket = io(window.location.origin);

Any idea why I'm getting two connections all the time? Thanks!

EDIT: Adding network screenshot.enter image description here

6
  • Is your web page reloading itself somehow? I'd suggest opening the network tab in the chrome debugger in the browser, check the box for [X] Preserve Log so it doesn't clear the log if the page reloads and then reload your page and watch exactly what requests are sent to your server. Since you aren't forcing a webSocket connection from the beginning, socket.io will do its usual 2-3 http requests before establish the persistent webSocket connection, but if your browser is accepting cookies, then those requests should all be part of the same connection and only trigger one connection event. Commented Apr 25, 2020 at 19:31
  • Thanks @jfriend00 I did that, but I'm not exactly sure what I'm looking for to see if the browser refreshed itself - and even if it did, wouldn't that disconnect the first connection and restart another? I'm not clear on why that would cause a duplicate. Another point: this happens on pages even when I have NO client side socket set up at all. Commented Apr 25, 2020 at 19:48
  • If you post a screenshot of that network tab right after you've seen two connect events, I can look at it. Commented Apr 25, 2020 at 20:07
  • What are you doing in this code require('../sockets')(io);? Any chance it is registering a second connect event handler? Commented Apr 25, 2020 at 20:08
  • If this is happening even on a web page that you think has no socket.io code in that page at all, then I think that's telling me that you have a duplicate set of socket.io client connection code that you're not aware of. You take out the one you are aware of, but the other one is still there. Show me a network tab screenshot of that page connecting to your server too and I'll take a look. Commented Apr 25, 2020 at 20:10

3 Answers 3

6

I solved my problem and wanted to share the solution here though I don't know exactly why what I was doing previously wasn't working.

I was using React Router in App.js, and I was importing socket.io-client in a component that got routed to. That was giving a double-connection for some reason (or more, depending on where I put the const socket = io(); line).

My solution was to import socket.io-client in App.js and pass io to the component as a prop where needed, like so:

import * as io from 'socket.io-client';

const socket = io();

class App extends Component {
 render() {
  return (
   <Router>
    <Header/>
    <Switch>
     <Route exact path="/" render={props => (<Home/>)}/>
     <Route exact path="/story" render={props => (<Start socket={socket} />)}/>
    </Switch>
   </Router>
  );
 }
}

export default App;

This defines the socket at a high level and passes down where needed, so nothing is getting called twice and I stay at one connection.

Sign up to request clarification or add additional context in comments.

Comments

3

OK, let's analyze your network trace in the screenshot. I'll start at the line that says "localhost" because that is presumably where you reloaded a page.

  1. localhost - Normal reload of a cached page
  2. 8 script files requested - All load normally
  3. Two socket.io requests arrive that are ?EIO=3&transport=polling&t=N6pOEHc. These are not normal requests. They are missing an sid=xxxxx value from the URL.
  4. A socket.io request arrives that is ?EIO=3&transport=polling&t=N6pOEKbsid=zhaGN0gOV6Qh3bg-AAAq. These look a normal socket.io connection initiation with a few polling requests before it switches over to a webSocket.
  5. A fetch Ajax request for incomplete arrives.
  6. A second socket.io polling request on the sid=zhaGN0gOV6Qh3bg-AAAq arrives. This again looks normal.
  7. A new socket.io request arrives from ?EIO=3transport=polling&t=N6pOEPQ&sid=wWH-VzFditNgmdWNAAAr. This is the second normal looking socket.io connection request. But, we don't know why there is a second attempt to connect.
  8. A webSocket connection sent out to socketjs-node and accepted (101 status) as a webSocket connection.
  9. Another socket.io polling request sent by sid=zhaGN0gOV6Qh3bg-AAAq. This is probably a request to convert to a webSocket connection, but is still marked as "pending" so it apparently did not succeed (as of the screenshot, perhaps never).
  10. Another polling request on the second socket.io connection sid=wWH-VzFditNgmdWNAAAr
  11. manifest.json and favicon.ico are requests
  12. 4 more polling requests from the second connection &sid=wWH-VzFditNgmdWNAAAr.
  13. 2 more polling requests from the first connection sid=zhaGN0gOV6Qh3bg-AAAq which definitely indicates that the previous attempt to turn this into a webSocket apparently did not work.

So, there are actually three socket.io attempts here. The first one looks a bit mal-formed, not sure why that is. The second two look like they are both initiated by client code. Neither one of them succeeds in switching to the webSocket transport.

My best guess would be that you have mismatched socket.io versions in client and server and thus they are having a hard time making the right type of lasting connection. It could also be that there's some sort of infrastructure in the way like a proxy that is preventing a webSocket connection from succeeding.

For other possible reasons, see this: Whats the problem with the socketio connection?


Another thing you can do for debugging purposes is to change the client code from this:

io(window.location.origin);

to this:

io(window.location.origin, {transports: ['websocket']});

This will force this connection attempt to ONLY connect with a webSocket. If we see a network trace from this, we can more clearly see whether a webSocket connection succeeds of fails.

It is also unusual to be using window.location.origin as the URL. If you just leave the URL out entirely, socket.io will just connect back to the host of the page which is generally what you want.

3 Comments

Thank you @jfriend00, I think this path is addressing another, likely important, issue I need to tackle, but not the questions I posted here. I posted the solution I came up with that is working as an answer to this question and will post a different question for the issue you're going after with more detail when I tackle it.
@YoungZaphod - so it was messed up client code that you never shared in the question. I guess this analysis was a waste of time.
Sorry you went through the effort and didn't get the answer accepted, but as I said what you caught is indeed an issue I need to tackle - so, not a waste of time, just not the solution to this particular issue. I posted the code I thought was relevant and I was wrong. It's not always clear at the beginning what's relevant.
0

Use Socket.once("connected") View the doc https://socket.io/docs/v4/listening-to-events/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.