Могу ли я получить свой 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-адрес, вам необходимо:
привязать сокет к определенному
localAddress
, поскольку это будет единственный локальный IP, который может вызватьonReceive
событие для этого сокета.проверьте список интерфейсов, о которых сообщает
chrome.system.network.getNetworkInterfaces()
, Если сообщается об 1 интерфейсе, это будет интерфейс, принимающий все пакеты, так что вы можете использовать егоaddress
, Однако, если сообщается о 2+ интерфейсах, вам придется анализировать префикс сети из пакета.remoteAddress
и сравнивайте это значение с префиксом каждого сообщаемого интерфейса, пока не найдете соответствие (при условии, что отправитель осуществляет вещание из той же сетевой подсети, к которой подключен локальный компьютер, а не через границы подсети).
При этом все это имеет значение только в том случае, если вам необходимо указать свой локальный IP-адрес в полезных данных широковещательного ответа. Скажем, есть 3 локальных интерфейса, и широковещательный пакет получен на интерфейсе 2. Ответ с localAddress
интерфейса 1 или 3, очевидно, будет неправильно, так как они находятся в других сетях, чем вещатель. Однако, если вам НЕ нужно ставить localAddress
в полезной нагрузке ответа, вещатель может просто посмотреть на remoteAddress
ответа, чтобы знать, каков ваш IP-адрес. Тогда вам вообще не нужно определять свой локальный IP-адрес, операционная система будет обрабатывать все для вас, когда вы отправляете ответ на remoteAddress
/remotePort
что вы получили трансляцию от.