I have an express server set up as follows to download torrents:
Server Side
const WebTorrent = require('webtorrent')
const client = new WebTorrent()
const express = require('express')
const app = express()
const port = 3001
const http = require('http')
const server = http.createServer(app)
const { Server } = require("socket.io");
const io = new Server(server, {
cors: {
origin: "http://localhost:3000"
}
});
app.io = io
//emitting works fine, but if more than one user sends a request to this endpoint, everyone gets all messages
app.get('/test', (req, res) => {
const link = req.query.magnetlink
req.app.io.emit('started', true)
client.add(link, (torrent) => {
const name = torrent.name
req.app.io.emit('started', true)
torrent.on('download, () => {
req.app.io.emit('data', () => {
name: name,
})
})
torrent.on('done', () => {
req.app.io.emit('done', () => {
name: name
})
})
})
})
server.listen(port, () => {
console.log(`Running on http://localhost:${port}`)
})
React Client Side
import * as React from 'react';
React.useEffect(() => {
socket.on('started', (data) => {
console.log(data)
//do something here
})
socket.on('data', (data) => {
console.log(data)
//do something here
})
}, [])
The post I got the base code from is almost 7 years old and doesn’t have much information on how to do these things, along with the socket.io docs that doesn’t really have any good information on this either.
There are two problems here. The first one is that all users are receiving the same messages which is a problem for my ui which adds the data to a state and it renders a part of the page with the new data. So I need every user who gets connected to get only their data that they requested.
The second problem is that using this method, I have no way of telling if the user is still connected to the route. If they are still connected I want to continue sending data, and if they aren’t I want to kill the process the server is doing to retrieve and send that data. Even emitting to the server inside of one of the ‘socket.on’ never gets received by the server. How do I go about checking if the client is still connected so I don’t waste bandwidth or waste storage space? I can’t use io.on(‘connect’) inside the route because I use it elsewhere to check if a user is online and count how many users are online. I just want to know if the user is still connected to the /test route specifically. Again, emitting works fine. I also want the messages to only be sent to that specific user connected to the /test route WHILE they are connected to the /test route. If the user refreshes their page or cancels I want to stop the data transfer on the server side which is doing things on its own.
2
Answers
I figured out my own solution. The steps are as follows:
Thanks for the help.
That’s because you’re doing
io.emit()
. That broadcasts to all connected clients. You need to dosocket.emit()
to the specific socket you want to send to.Uses are never connected to a route. An express route is a temporal thing. Some client makes an http request to a route. The response gets sent. The http request/route is now over. There is no connection to a route.
A client can make a socket.io connection to a server. That makes a continuous connection between client and server that has NOTHING at all to do with a specific route. That’s a connection between that specific client and the server.
If you use that socket.io connection to then request the download, then when you get the result of that download, you can send it back over the same socket that requested it. You don’t have to try to match a socket with a route at all. You get a request on the socket and you send the response back on the same socket.
I don’t know your torrent code, but the general structure would be like this:
Do not initiate your torrent stuff with the http URL because you don’t know which socket.io connection belongs to that client making that http request or if there even is one yet.