Некоторые вопросы о пакете Java
У меня недавно нос нырнул в программирование сокетов с помощью java, и у меня есть несколько общих вопросов.
Существует метод bind(), а также connect() и disconnect(). Нет unbind(). Это связано с тем, что при отсоединении сокет несвязан? Собирает ли сбор мусора это после выхода программы? Или это даже не вопрос?
Кроме того, при создании DatagramSocket, как это отличается, если я предоставляю только порт и адрес? Я создаю программу для сбора данных из сети, так как данные всплывают и регистрируются. Должен ли я использовать локальный адрес? Не удалось использовать адрес при создании сокета, чтобы я не мог собирать пакеты?
Я просто пытаюсь получить более глубокое понимание внутренней работы этих вещей.
Ответы
Ответ 1
Там около 15 независимых вопросов, но я сделаю все возможное, чтобы их решить:
Существует метод bind(), а также connect() и disconnect(). Нет unbind(). Это связано с тем, что при отсоединении разъем не подключен?
bind()
отделен от connect()
и disconnect()
. Bind используется для привязки сокета к определенному порту - эффективно для "прослушивания" соединений, тогда как connect()
используется для открытия подключения к сокету, который уже прослушивает определенный порт. Эквивалентом unbind()
является close()
Собирает ли сборку мусора это после выхода программы? Или это даже не вопрос?
Это абсолютно правильный вопрос, хотя сборка мусора - это технология, используемая для управления памятью, а не управление ресурсами сокета/ОС. Если вы не освободите определенный порт, он останется связанным с вашим приложением до тех пор, пока ваше приложение не завершится, и оно будет восстановлено ОС. Это функциональность на уровне ОС, а не функциональность JVM и т.д.
Кроме того, при создании DatagramSocket, как это отличается, если я предоставляю только порт или предоставляю порт и адрес?
В какой-то момент вам необходимо указать интернет-адрес и порт или сокет, к которому вы хотите подключиться или для привязки. Нет.
Я создаю программу для сбора данных из сети, так как данные всплывают и регистрируются. Должен ли я использовать локальный адрес? Не удалось использовать адрес при создании сокета, чтобы я не мог собирать пакеты?
Я не уверен, что вы просите здесь, вы говорите о регистрации всех пакетов в сети, ака-то это сниффер? Это потребует больше, чем простое программирование дейтаграмм. Фактически вам приходится вводить себя на уровне сетевого адаптера, чтобы перехватывать пакеты, поскольку они считываются с линии. То, о чем вы говорите, позволит вам получать пакеты, которые отправляются на конкретный порт, который вы слушаете.
Ответ 2
A DatagramSocket
остается связанным при отключении, это метод close()
, который отменит его. Обратите внимание, что для сокета UDP (датаграммы) семантика connect()
и disconnect()
отличается от сокета TCP (или другого ориентированного на соединение). UDP - это протокол без установления соединения, а связанный DatagramSocket
может отправлять и принимать пакеты без "подключения". Метод connect()
имеет чисто локальный эффект, поскольку он заставляет сокет иметь возможность отправлять и принимать пакеты только на конкретный хост/порт, то есть действовать как фильтр. A DatagramSocket
, подключенный к многоадресному или широковещательному адресу, сможет отправлять пакеты и не принимать их.
bind(SocketAddress)
используется для присоединения сокета к локальной комбинации адресов/портов, прежде чем сокет привязан, он не может принимать или отправлять какие-либо пакеты. Поведение конструкторов по умолчанию заключается в немедленной привязке сокета. Чтобы создать несвязанный 'DatagramSocket', используйте конструктор DatagramSocket(SocketAddress)
, передающий null
в качестве аргумента. Затем можно применить произвольную конфигурацию к сокету, прежде чем привязать его к bind()
.
Насколько я знаю, открытый DatagramSocket
, выходящий за пределы области действия, приведет к утечке ресурса, объект может быть собран с помощью мусора, но я уверен, что базовый UDP-сокет останется выделенным ОС до тех пор, пока JVM выходы процесса.
Если адрес не указан до того, как сокет привязан, он привязан к подстановочному адресу (INADDR_ANY
), чтобы он мог получать и отправлять пакеты из любого доступного локального адреса (если только он не подключен позднее к некоторому хосту). Если порт не указан (или указан как 0), то сокет привязан к некоторому доступному порту, выбранному ОС (эфемерный порт).
Изменить: пример
// bind to INADDR_ANY, allowing packets on all IP addresses of host:
DatagramSocket dsock = new DatagramSocket(55555);
DatagramPacket packet = new DatagramPacket(new byte[8192]);
//next packet can be from anywhere including local host (127.0.0.0/8)
dsock.receive(packet);
// restrict communication to a single host/port:
dsock.connect(new InetSocketAddress("somehost.net", 99));
// next packet can only be from somehost.net on port 99:
dsock.receive(packet);