js/vue获取本机的IP地址遇到的问题解决经验

  再做前端页面的时候,想获取本地的ip地址,可能是为了和服务器通信,可能是为了展示,无论哪种,目的要获取js get IP

 相信大家搜到最多的是以下的js方法(都是超来抄去),我来讲讲我遇到的坑,方法虽然很笨,只为了解决问题。

这里要强调下,我们这里是获取本机IP,局域网或者独立电脑,木有联网,若是借用网络接口,如搜狐、新浪等接口地址不行,因为木有网络。就是那种我一打开网页就直接获取了。

方法一:

getUserIP(onNewIP) { //  onNewIp-新IP的侦听器函数//兼容 firefox和 chrome浏览器var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;//定义参数var pc = new myPeerConnection({iceServers: []}),noop = function() {},localIPs = {},ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,key;function iterateIP(ip) {if (!localIPs[ip]) onNewIP(ip);localIPs[ip] = true;}//create a bogus data channelpc.createDataChannel("");// create offer and set local descriptionpc.createOffer().then(function(sdp) {sdp.sdp.split('\n').forEach(function(line) {if (line.indexOf('candidate') < 0) return;line.match(ipRegex).forEach(iterateIP);});pc.setLocalDescription(sdp, noop, noop);}).catch(function(reason) {// An error occurred, so handle the failure to connect});//sten for candidate eventspc.onicecandidate = function(ice) {if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;ice.candidate.candidate.match(ipRegex).forEach(iterateIP);};//  console.log("ip1:"+ip);},

方法二:

getUserIP(){var $this = thisvar RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;if (RTCPeerConnection) (function () {var rtc = new RTCPeerConnection({iceServers:[]});if (1 || window.mozRTCPeerConnection) {     rtc.createDataChannel('', {reliable:false});};rtc.onicecandidate = function (evt) {if (evt.candidate) grepSDP("a="+evt.candidate.candidate);};rtc.createOffer(function (offerDesc) {grepSDP(offerDesc.sdp);rtc.setLocalDescription(offerDesc);}, function (e) { console.warn("offer failed", e); });var addrs = Object.create(null);addrs["0.0.0.0"] = false;var currentIP2function updateDisplay(newAddr) {if (newAddr in addrs) return;else addrs[newAddr] = true;var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });for(var i = 0; i < displayAddrs.length; i++){if(displayAddrs[i].length > 16){displayAddrs.splice(i, 1);i--;}}// return displayAddrs[0];alert("ip" + displayAddrs[0]);}function grepSDP(sdp) {var hosts = [];sdp.split('\r\n').forEach(function (line, index, arr) {if (~line.indexOf("a=candidate")) {    var parts = line.split(' '),       addr = parts[4],type = parts[7];if (type === 'host') updateDisplay(addr);} else if (~line.indexOf("c=")) {       var parts = line.split(' '),addr = parts[2];updateDisplay(addr);}});}})()}

还有好几种,就不一一列举了。

以上的方法我验证是可以的,如何调用:

getUserIP(function(ip){alert("Got IP! :" + ip);
});

其实这样就可以调用出来了,但是这里我只想让这个IP变为全局,我我需要访问服务端的时候可以用(服务端和前端放在一台服务器,不能分开);

这里大家想说那直接用127.0.0.1不就可以了,问题是与后端交互中,发现无法通信,必须写服务端的地址。那我们两放在一起,我只要获取我本机地址即可。

那么问题来了一:

根据上面的方法,发现必须得使用回调getUserIP才能获取ip,要是再这个回调方法外得IP无效,例如:

var getIP getUserIP(function(ip){alert("Got IP! :" + ip);getIP = ip;
});console.log("外部打印IP:",this.getIP)

这个你就会发现,再外部打印是为空得,这个只能再这个回调方法使用,也是非常麻烦之一;

有人会想到VUE中使用main.js得prototype全局方法,详情:网站整改公告 - 博客园团队 - 博客园

先把上面的方法写在一个'../src/util/main.js'下抛出;

import Vue from "vue";
import App from "./views/App";
import oIp1 from '../src/util/main';Vue.config.productionTip = false;Vue.prototype.$getIP=oIp1
// console.log(configN);//测试该方法是否实现,方法再oIp1里
oIp1.getUserIP((ip)=>{debugger;console.log('newIp=>',ip);
});new Vue({});

再任何地方就可以调用$getIP了。很遗憾,不知道我得框架里写了多个new Vue({ }); 这种方法对我来说不行,(不知道哪个人写得框架),其实不一定能用,接着看下面

问题二:

我们发现回调获取ip时获取不到,打印出来ip时空的,这是为什么?

大家注意下这些方法的判断if (line.indexOf('candidate') < 0),注意:candidate这个我打印出来发现木有此项,换成c=IN就有0.0.0.0,这个到底是什么原因,我以为是我电脑连接wifi的和连接网线的(之前连接网线可以)的区别?然后找根网线再试试发现不行,那么估计是环境问题了(要详细网络大神,他们说亲试可以,肯定是可以的)。

针对这个单独百度查了candidate项,才发现是浏览器默认是被限制了,就是为了安全,浏览器不允许你获取地址。参考:获取本机ip失败,webrtc candidate xxx.local mDNS ip地址问题_梦想身高1米8的博客-CSDN博客

谷歌解决办法

浏览器输入chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
将Anonymize local IPs exposed by WebRTC置为disabled

火狐解决办法

浏览器输入about:config
将media.peerconnection.ice.obfuscate_host_addresses置为false

然后再运行,就有地址弹出了。

问题三:

问题又绕回来,上面的方法只能做回调方法里使用,不能做全局,很多人应该可以想到,写个方法接收里面的参数,例如:

var getIP getUserIP(function(ip){alert("Got IP! :" + ip);test(ip)//调用这个方法,把这个ip值传出去
});//写一个方法
test(ip){getIP = ip;
};console.log("外部打印IP:",this.getIP)

呵呵,不好意思,上面的方法打印出来的getIp还是空的,获取不到。

我又把方法优化了下,方法三:

getUserIP(){if(typeof window != 'undefined'){var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;if (RTCPeerConnection) (()=>{var rtc = new RTCPeerConnection()rtc.createDataChannel(''); //创建一个可以发送任意数据的数据通道rtc.createOffer( offerDesc => { //创建并存储一个sdp数据rtc.setLocalDescription(offerDesc)}, e => { console.log(e)})rtc.onicecandidate =(evt) => { //监听candidate事件if (evt.candidate) {console.log('evt:',evt.candidate)let ip_rule = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/var ip_addr = ip_rule.exec(evt.candidate.candidate)[1]console.log('ip_addr:',ip_addr)   //打印获取的IP地址this.test(ip_addr);//调用方法把ip地址的值传出去}}})()else{console.log("没有找到")}}},

这个方法一看也是需要回调,但是我们不想回调;大家发现方法一有参数,不回调木有办法使用,不然你传什么值,而方法二和三,直接执行即可

getUserIP();//直接执行(运行)该方法

只要再方法二和方法三里调用外部方法,把ip参数传过去

var getIP
test(ip){console.log("把ip地址传过来",ip)//这里就可以把ip传给全局的变量了getIP = ip;
}console.log("外部打印IP:",getIP)

那样你爱怎么用这个getIp就怎么用。

最后。。。最后。。。还有更残酷的事实:

我们获取IP的目的就是把web前端打包给客户,但不知道客户的IP,不可能写死,和服务端再一台电脑中部署,127.0.0.1不能与服务端交互,那怎么办?

发现localhost竟然可以通信,这样直接写死就行,放在哪台电脑都可以用,弄了这么久,这127.0.0.1和localhost区别大家自行百度吧!坑大了。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部