Я пытаюсь построить свой текущий проект таким образом, чтобы мои друзья могли создавать серверы в одной сети, чтобы мы могли подключаться друг к другу (в значительной степени через локальную сеть). Единственная проблема заключается в том, что когда я запускаю свою программу в двух окнах терминала, мой второй запуск завершается неудачей и выдает мне ошибки, поскольку порты уже заняты, что логично.
Я работаю с Vite, express и ws. Это один из кодов моего сервера.
const { WebSocketServer } = require('ws')
const sockserver1 = new WebSocketServer({ port: 311 })
sockserver1.on('connection', ws => {
sockserver1.clients.forEach(client => {
client.send(`A new player connection has been established`);
})
ws.on('message', data => {
sockserver1.clients.forEach(client => {
client.send(`${data}`)
})
})
ws.on('close', () => {
sockserver1.clients.forEach(client => {
client.send(`A player has disconnected`)
})
})
ws.onerror = function () {
console.info('websocket error')
}
});
Когда я запускаю это во второй раз, он терпит неудачу и сообщает, что порт :: 311 занят. Как я могу добавить 1 к номеру порта, пока не найду тот, который не занят? Я заметил, что Vite делает это.
Это... не выдает мне ошибку для этого сервера! Следующий сервер выдает мне ошибку, поскольку для него установлено значение, отличное от 0.
Однако localhost:0 ограничен.
Этот вопрос похож на: Случайные свободные TCP-порты Nodejs. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.
@jabaa Ой, да, это может быть дубликат. Я пытался узнать, был ли уже подобный вопрос
«Как я могу добавить 1 к номеру порта, пока не найду тот, который не занят? Я заметил, что Vite делает это». Vite имеет открытый исходный код. Вы можете проверить это в исходном коде. github.com/vitejs/vite
Не думаю, что мне рекомендовали этот вопрос. Как закрыть вопрос?
Я не уверен, сможете ли вы закрыть свои вопросы своей репутацией. Вы можете либо удалить его, либо подождать, пока другие его закроют.
Что ж, я удовлетворен ответом Энстона, так что я согласен, что мой вопрос будет закрыт. Спасибо всем!
Имейте в виду, что принятый ответ может вызвать состояние гонки. Для хобби-проекта это нормально, но в продакшене это баг.
Да. Я буду иметь это в виду. Спасибо, Джабаа!
@Алекс, посмотри на мой исправленный ответ
Попробуйте создать метод, который проверяет текущий порт и пробует следующий, если он занят.
Вот как это будет выглядеть:
const { WebSocketServer } = require('ws');
const net = require('net');
function findAvailablePort(startPort, callback) {
const server = net.createServer();
server.listen(startPort, () => {
server.once('close', () => {
callback(startPort);
});
server.close();
});
server.on('error', () => {
findAvailablePort(startPort + 1, callback);
});
}
findAvailablePort(311, (availablePort) => {
const sockserver1 = new WebSocketServer({ port: availablePort });
console.info(`WebSocket server started on port ${availablePort}`);
sockserver1.on('connection', ws => {
sockserver1.clients.forEach(client => {
client.send(`A new player connection has been established`);
});
ws.on('message', data => {
sockserver1.clients.forEach(client => {
client.send(`${data}`);
});
});
ws.on('close', () => {
sockserver1.clients.forEach(client => {
client.send(`A player has disconnected`);
});
});
ws.onerror = function () {
console.info('websocket error');
}
});
});
Это может вызвать состояние гонки. Порт может быть свободным при создании сервера в тестовой функции и использоваться другой программой при создании реального сервера. Вам следует либо использовать реальный сервер для теста, либо запросить порт у операционной системы. Ваш подход может время от времени давать сбой. В зависимости от количества параллельных серверов вам придется протестировать множество портов, прежде чем вы найдете свободный.
Вы пробовали это с портом 0? В ОП написано, они попробовали, но это не работает так, как вы описали.
Я попробовал, и это работает. Я не понимаю. Где Алекс говорит, что это не работает?
Я имею в виду, нужно ли мне присылать скриншоты работы? Что я сделал? Это были мои ненужные комментарии ранее?
Я проголосовал против, потому что ОП прямо написал в комментарии, что port: 0
у них не работает. Если это сработает, вопрос требует дополнительных разъяснений. Ответ, который не работает для ОП, бесполезен.
Это когда он сказал, что localhost:0 ограничен? Я даже не уверен, что это значит
Ладноааа тогда. Ответ отменен
Да, это то, что я имел в виду. Вы попросили ОП использовать порт 0, и ответ заключался в том, что первый сервер был запущен на порту 0, а второй сервер вышел из строя. Это не имеет особого смысла, но я не пробовал и доверял ОП. Я отменил свой отрицательный голос.
Это просто странно, потому что это сработало, когда я его запустил. Каждый раз он использует другой порт. Обычно порт стоит 30 тысяч на винде
Возможно, проблема в том, что я доверял заявлению ОП. Возможно, ОП сделал что-то не так.
Вот сообщение, которое я получаю, когда пытаюсь его открыть (вероятно, мне следовало отправить его раньше): «Этот адрес использует сетевой порт, который обычно используется для целей, отличных от просмотра веб-страниц. Firefox отменил запрос в целях вашей защиты». Chrome не может получить доступ к серверу. Я тоже не уверен, почему порт 0 работает. Это происходит от порта 0 до порта 9. Порт 10 работает нормально. Это еще один вопрос, который мне следует задать? Посмотрите, знает ли кто-нибудь еще, в чем может быть проблема?
@Alex Не пытайтесь открыть адрес с портом 0. Порт 0 не существует. Это особое значение, которое сигнализирует операционной системе о том, что вам нужен случайный свободный порт. Операционная система выбирает порт для сервера. Вам нужно узнать этот порт и использовать его в своем клиенте. Пожалуйста, предоставьте более подробную информацию и информацию об отладке в будущем. «Это... не выдает мне ошибку для этого сервера! Следующий сервер выдает мне ошибку, поскольку для него установлено значение, отличное от 0. Однако Localhost:0 ограничен». это бесполезно.
Я думаю, что теперь, когда у него есть ответ, этот вопрос его больше не волнует. Я имею в виду, я был таким раньше
Нет, я знаю. Я пытаюсь помочь вам понять, что я делаю, чтобы мы все знали, что происходит.
@jabaa Полезно знать на будущее. Что касается комментария, который вам не помог, я имел в виду, что когда я запускаю сценарий дважды, я не получаю сообщение об ошибке о том, что порт 0 уже занят, но я получаю сообщение об ошибке, что другие порты для другого сервера заняты. Я не рассказал вам о других серверах, поэтому моя ошибка.
Я новичок в подобных веб-сайтах, поэтому пытаюсь выработать хорошие привычки общения (особенно для Stack Overflow).
@Alex Так мой новый ответ подойдет тебе или нет? Вот что мне действительно хотелось бы знать
Да, это работает. Я проверил ваше последнее редактирование, и оно работает, так что спасибо Анстону Соренсену и Джабаа за уделенное время. Я все еще буду помнить о состоянии гонки. И, к счастью, мой проект предназначен только для моих друзей, поэтому я могу их предупредить.
@Alex Вопрос в том, работает ли port: 0
. Это был бы правильный ответ. Он не тестирует порты и не имеет состояния гонки. Если я правильно понимаю, комментарии под вашим вопросом неверны. Серверы запустились правильно, но вы не знали правильный URL-адрес клиента.
Этот пакет поможет вам с такими потребностями: https://github.com/sindresorhus/get-port
Это также имеет проблему состояния гонки. get-port
может вернуть свободный порт, который используется другой программой, прежде чем сервер сможет к нему привязаться. Я бы не рекомендовал этот пакет.
Что делает установка порта на 0?