Могу ли я получить свой IP-адрес в приложении Chrome без использования внешней службы?

Я создаю приложение Chrome и создал сокет UDP через API Chrome Socket.

Есть ли способ получить свой собственный IP-адрес без использования внешней службы? Что я имею в виду под "собственным IP-адресом": и клиент, и сервер находятся в одной сети. Приложение chrome должно отвечать на широковещательную рассылку UDP с собственным локальным IP-адресом.

На самом деле есть API-интерфейс Chrome Socket именно для этого варианта использования. Но, к сожалению, я получаю только следующий объект обратного вызова: Object {paused: false, persistent: false, socketId: 17}, который пропускает localAddress приписывать. Это (необязательный) атрибут в SocketInfo объект согласно документации. По сути это код, который я запускаю:

chrome.sockets.udp.create({}, function(socketInfo){
    chrome.sockets.udp.getInfo(socketInfo.socketId, function (detailedInfo){
        ipAddress = detailedInfo.localAddress;
        console.debug(detailedInfo); // containts no `localAddress`
    });
});

Я также не думаю, что мне не хватает каких - либо разрешений на манифест, поскольку в документации API нет специальных разрешений. Это то, что я использую:

"sockets": {
  "udp": {
    "send": "*",
    "bind": "*"
  }
}

Когда я использую Python, я могу достичь этой цели следующим образом:

import socket
ip_address = socket.gethostbyname(socket.gethostname())

Любая помощь будет отличной!

3 ответа

Решение

Оказывается, я использовал неправильный API. Для моего случая использования мне нужно было использовать chrome.system.network.getNetworkInterfaces.

Это вернет массив всех интерфейсов с их IP-адресом.

Это мой пример кода:

chrome.system.network.getNetworkInterfaces(function(interfaces){
    console.log(interfaces);
});

манифест-разрешения:

"permissions": [
  "system.network"
],

С учетом комментариев сделать идеальное решение нелегко, так как нужно найти правильный интерфейс для UDP-порта.

На данный момент единственный способ идеально соответствовать интерфейсу bind все адреса для всех интерфейсов, заданных getNetworkInterfaces, Затем вы точно знаете, какой интерфейс использовался для приема вызова, и вы можете ответить с правильным IP-адресом.

Неподключенный сокет еще не имеет локального адреса, если он не связан с адресом. Он получает локальный и удаленный адрес только после подключения сокета (TCP) или отправки данных через сокет (UDP). И он получает только IP-адрес локальной машины, тогда как внешняя служба видит внешний адрес маршрутизатора, выходящий в Интернет, если вы находитесь за каким-то NAT-маршрутизатором (то есть большинством домашних пользователей).

Обратный звонок, который вы предоставляете udp.create() вызывается, когда сокет был изначально создан, а не когда сокет получает пакеты. Во время создания сокет не связан ни с каким localAddress или же localPort еще. Вы должны позвонить udp.bind() установить конкретный localPort (и, возможно, конкретный localAddress) что сокет будет прослушивать пакеты. если ты bind() в "0.0.0.0" тогда сокет будет прослушивать все локальные IP-адреса.

Когда приходит новый пакет, udp.onReceive событие сработало. Пакет был получен определенным localAddressОднако Chrome API не предоставляет средства для прямого запроса localAddress получил пакет (основной recvfrom() функция сокета не предоставляет эту информацию). Чтобы обнаружить принимающий локальный IP-адрес, вам необходимо:

  1. привязать сокет к определенному localAddress, поскольку это будет единственный локальный IP, который может вызвать onReceive событие для этого сокета.

  2. проверьте список интерфейсов, о которых сообщает chrome.system.network.getNetworkInterfaces(), Если сообщается об 1 интерфейсе, это будет интерфейс, принимающий все пакеты, так что вы можете использовать его address, Однако, если сообщается о 2+ интерфейсах, вам придется анализировать префикс сети из пакета. remoteAddress и сравнивайте это значение с префиксом каждого сообщаемого интерфейса, пока не найдете соответствие (при условии, что отправитель осуществляет вещание из той же сетевой подсети, к которой подключен локальный компьютер, а не через границы подсети).

При этом все это имеет значение только в том случае, если вам необходимо указать свой локальный IP-адрес в полезных данных широковещательного ответа. Скажем, есть 3 локальных интерфейса, и широковещательный пакет получен на интерфейсе 2. Ответ с localAddress интерфейса 1 или 3, очевидно, будет неправильно, так как они находятся в других сетях, чем вещатель. Однако, если вам НЕ нужно ставить localAddress в полезной нагрузке ответа, вещатель может просто посмотреть на remoteAddress ответа, чтобы знать, каков ваш IP-адрес. Тогда вам вообще не нужно определять свой локальный IP-адрес, операционная система будет обрабатывать все для вас, когда вы отправляете ответ на remoteAddress/remotePort что вы получили трансляцию от.

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