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 channel
             pc.createDataChannel("");
    
             // create offer and set local description
             pc.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 events
             pc.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 = this
        var 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 currentIP2
            function 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全局方法,详情:https://www.cnblogs.com/cmt/p/14553189.html

先把上面的方法写在一个'../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项,才发现是浏览器默认是被限制了,就是为了安全,浏览器不允许你获取地址。参考:https://blog.csdn.net/weixin_43915401/article/details/111830699

谷歌解决办法

浏览器输入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区别大家自行百度吧!坑大了。
————————————————
版权声明:本文为CSDN博主「享有盛誉之名」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bbs11007/article/details/114982607

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值