Должен ли я использовать те же номера портов при отправке данных через UDP?

Я только что реализовал базовое приложение на основе сокетов, ничего особенного. Ради экономии времени мой сервер-клиент действует как сервер и клиент одновременно.

Когда мы отправляем данные (в данном случае) клиенту / серверу, имеет ли это значение использовать тот же номер порта? Я думаю, нет, потому что не имеет значения, какой порт вы используете при отправке данных. Необходимо сохранить только одно: порт должен быть любым доступным на машине получателя, и если этот получатель решит отправить что-то обратно, у него будет достаточно информации об отправителе: его IP-адрес, номер порта и т. Д. Насколько я знаю, полученный пакет предоставляет всю эту информацию.

Ниже приведена лишь иллюстрация того, что я сказал выше.

public class Server {

    public static void main(String[] args) {
        GameServer server = new GameSever(9822);
        server.start();

        InetAddress address = null;
        int port = 7877;
        try {
            address = InetAddress.getByName("192.168.0.2");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        server.send(new byte[] { 1, 2, 3 }, address, port);
    }
}

3 ответа

Решение

Когда мы отправляем данные (в данном случае) клиенту / серверу, имеет ли это значение использовать тот же номер порта? Я думаю, нет, потому что не имеет значения, какой порт вы используете при отправке данных.

Во-первых, различайте термины клиент и сервер (как обычно клиент инициирует, отправляя сообщение, на которое сервер отвечает).

Далее, порт, который вы используете, логически не имеет значения, причина в том, что сервер использует request.getPort() определить порт во время заполнения ответа; (запрос представляет собой DatagramPacket, отправленный клиентом).

Хотя вы можете жестко закодировать порт на сервере (если он известен заранее), но это плохая идея. Что в тех приложениях, где вы не знаете, кто отправил пакет дейтаграмм?

Документация по Java от Oracle также использует пример клиент-сервер, где номер порта клиента оставлен на усмотрение конструктора. Это упоминает:

В основном клиент использует конструктор, которому не требуется номер порта. Этот конструктор просто связывает DatagramSocket с любым доступным локальным портом. Не имеет значения, к какому порту подключен клиент, потому что DatagramPackets содержит информацию об адресации. Сервер получает номер порта из DatagramPackets и отправляет свой ответ на этот порт.


ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (взято из Java Network Programming):

public DatagramSocket() throws SocketException

Этот конструктор создает сокет, который привязан к анонимному порту. Например:

DatagramSocket client = new DatagramSocket();

Выберите этот конструктор для клиента, который инициирует диалог с сервером. В этом случае вам не важно, к какому порту подключен сокет, потому что сервер отправит свой ответ на порт, с которого произошла датаграмма. Разрешение системе назначить порт означает, что вам не нужно беспокоиться о поиске неиспользуемого порта. Если по какой-то причине вам нужен локальный порт, вы можете узнать это с помощью метода getLocalPort().

ПРИМЕЧАНИЕ. Один и тот же сокет может принимать дейтаграммы, которые ему отправляет сервер (базовая реализация).

Принимая во внимание, что приведенный ниже конструктор создает сокет, который прослушивает входящие дейтаграммы на конкретном порту, заданном аргументом порта:

public DatagramSocket(int port) throws SocketException

Используйте этот конструктор, чтобы написать сервер, который прослушивает известный порт.

Когда сервер прослушивает компьютер, он указывает порт, к которому он хочет подключиться, поэтому порты важны для настройки серверов. Это полезно, поскольку у вас может быть несколько приложений, прослушивающих через разные порты, при этом разные приложения случайно не общаются друг с другом. Поэтому вам следует выбрать порт, который не является стандартным (например, 80 для HTTP), который будет использоваться исключительно для вашего игрового сервера, чтобы клиент знал, на какой порт отправлять запросы.

Если вы хотите обрабатывать несколько соединений одновременно, лучше всего использовать потоки.

Короткий ответ:
Ваше предположение верно.

Более длинный ответ:
Клиент получает случайный номер порта при отправке данных на сервер, и каждый пакет имеет заголовок, который содержит информацию о порте клиента, IP-адрес и т. Д. Таким образом, сервер может легко получить эту информацию и отправить все обратно.

В то время как сервер должен быть привязан к определенному порту, чтобы клиенты могли отправлять данные на этот сервер, потому что при использовании UDP необходимо указать IP-адрес и порт.

Другие вопросы по тегам