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.
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.
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.
?EIO=3&transport=polling&t=N6pOEHc
. These are not normal requests. They are missing an sid=xxxxx
value from the URL.?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.incomplete
arrives.sid=zhaGN0gOV6Qh3bg-AAAq
arrives. This again looks normal.?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.socketjs-node
and accepted (101 status) as a webSocket connection.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).sid=wWH-VzFditNgmdWNAAAr
&sid=wWH-VzFditNgmdWNAAAr
.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With