在 Heroku 中为 bittorrent-tracker 服务器使用单个端口

Using a single port for bittorrent-tracker server in Heroku

我正在尝试 build/deploy 一个跟踪器服务器,用于使用以下代码的 P2P 应用程序。它在本地工作正常,但是当我将它部署到 Heroku 时,端口绑定失败,因为只允许一个端口。

    // Create a web sockets signaling server
    var express = require('express');
    var bodyParser = require('body-parser');
    var app = express();

    //Allow all requests from all domains & localhost
    app.all('/*', function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
        res.header("Access-Control-Allow-Methods", "POST, GET");
        next();
    });

    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({extended: false}));

    let lookup = {}

    const hostname = '0.0.0.0';
    const port = process.env.PORT;

    var Server = require('bittorrent-tracker').Server

    var server = new Server({
        udp: false, // enable udp server? [default=true]
        http: true, // enable http server? [default=true]
        ws: true, // enable websocket server? [default=true]
        stats: true, // enable web-based statistics? [default=true]
    })

    server.on('error', function (err) {
        // fatal server error!
        console.log(err.message)
    })

    server.on('warning', function (err) {
        // client sent bad data. probably not a problem, just a buggy client.
        console.log(err.message)
    })

    server.on('listening', function () {
        // fired when all requested servers are listening
        console.log('Signal server http port:' + server.http.address().port)
        console.log('Signal server ws port:' + server.ws.address().port)
    })

    // start tracker server listening! Use 0 to listen on a random free port.
    server.listen(port, hostname, 'listening')

    // listen for individual tracker messages from peers:
    server.on('start', function (addr) {
        console.log('got start message from ' + addr)
        Object.keys(server.torrents).forEach(hash => {
            lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
            console.log("peers: " + server.torrents[hash].peers.length)
        })
    })

    server.on('complete', function (addr) {})
    server.on('stop', function (addr) {})

    app.get('/peers', function(req, res) {
        res.send(lookup);
    })

    app.listen(process.env.PORT, function() {
        console.log('Express server port: ' + this.address().port); //Listening on port #
    })

如果我对 serverapp 使用 process.env.PORT,我会得到以下结果,这是预期的,因为 Heroku 只允许 1 个监听端口:

2021-02-13T05:35:31.016101+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:35:30.885170+00:00 app[web.1]: Express server port: 9898
2021-02-13T05:35:30.885204+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
2021-02-13T05:35:30.885205+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898

如果我对 serverapp 的端口进行硬编码,应用程序可以正常启动,但信令服务器无法正常工作。没有生成大量日志记录。

2021-02-13T05:38:21.141806+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:38:20.998054+00:00 app[web.1]: Express server port: 25702
2021-02-13T05:38:20.998550+00:00 app[web.1]: Signal server http port:31415
2021-02-13T05:38:20.998683+00:00 app[web.1]: Signal server ws port:31415

bittorrent-tracker服务器和express服务器可以使用同一个端口吗?例如,我是否可以在根本不需要 express 的情况下获取和 return 此代码块中的对等方列表?

    server.on('start', function (addr) {
        console.log('got start message from ' + addr)
        // Could I do something here to eliminate the need for Express?
        Object.keys(server.torrents).forEach(hash => {
            lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
            console.log("peers: " + server.torrents[hash].peers.length)
        })
    })

documentation 状态:

The http server will handle requests for the following paths: /announce, /scrape. Requests for other paths will not be handled.

但也许我可以通过某种方式填充 express 正在处理的请求?

在问了这个问题后不久,我突然想到我可能根本不需要 express。结果证明是对的。

对于任何想要 Heroku-ready bittorrent-tracker 的人,这里是更新的代码:

// Create a web sockets signaling server
let lookup = {}

const hostname = '0.0.0.0';
const port = process.env.PORT;


var Server = require('bittorrent-tracker').Server

var server = new Server({
    udp: false, // enable udp server? [default=true]
    http: true, // enable http server? [default=true]
    ws: true, // enable websocket server? [default=true]
    stats: true, // enable web-based statistics? [default=true]
})

server.on('error', function (err) {
    // fatal server error!
    console.log(err.message)
})

server.on('warning', function (err) {
    // client sent bad data. probably not a problem, just a buggy client.
    console.log(err.message)
})

server.on('listening', function () {
    // fired when all requested servers are listening
    console.log('Signal server http port:' + server.http.address().port)
    console.log('Signal server ws port:' + server.ws.address().port)
})

// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')

// listen for individual tracker messages from peers:
server.on('start', function (addr) {
    console.log('got start message from ' + addr)
    Object.keys(server.torrents).forEach(hash => {
        lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
        console.log("peers: " + server.torrents[hash].peers.length)
    })
})

server.on('complete', function (addr) {})
server.on('stop', function (addr) {})