Javascript IP地址存储为int会导致溢出吗?

Javascript IP地址存储为int会导致溢出吗?,javascript,Javascript,我正在node.js中编写一个聊天服务器,我想将连接用户的IP地址作为(无符号)整数存储在mysql数据库中。 我已经编写了一个javascript方法来将ip地址转换为字符串和整数。然而,我得到了一些奇怪的结果 这是我的密码: function ipToInt(ip) { var parts = ip.split("."); var res = 0; res += parseInt(parts[0], 10) << 24; res += parse

我正在node.js中编写一个聊天服务器,我想将连接用户的IP地址作为(无符号)整数存储在mysql数据库中。 我已经编写了一个javascript方法来将ip地址转换为字符串和整数。然而,我得到了一些奇怪的结果

这是我的密码:

function ipToInt(ip) {
    var parts = ip.split(".");
    var res = 0;

    res += parseInt(parts[0], 10) << 24;
    res += parseInt(parts[1], 10) << 16;
    res += parseInt(parts[2], 10) << 8;
    res += parseInt(parts[3], 10);

    return res;
}
功能ipToInt(ip){
var部分=ip分割(“.”);
var-res=0;

res+=parseInt(parts[0],10)您向左移位以获得原始数字,即不考虑符号的4组位


右移返回IP。不管符号是什么。

执行无符号右移的“>>”结果。

V4空间中的IP地址是无符号32位数字,因此FF.FF.FF的IP地址是2^32,不能大于该数字。请参阅:

要将该数字转换回IP地址,必须将该数字分解为4个部分,因为每个字节都是地址的一个八位字节,所以请将该数字转换为十六进制,然后解析出每对数字。您可能需要也可能不需要为第一个八位字节添加前导零


此外,您可能需要处理整数的字节顺序(endien问题),但由于现在大多数系统都是基于intel的,您可能不需要处理这个问题。

为什么转换后的IP是负数?

var aaa = Number("0b"+ "192.168.2.44".split(".").map(
  function(dec){
    return ("00000000" + Number(dec).toString(2)).slice(-8); 
  }).join(""));

aaa.toString(2).match(/.{1,8}/g).map(
  function(bin){
    return Number("0b"+bin); 
  }).join(".");
这不是溢出。IP地址的第一部分是192,它转换成11000000的二进制。然后将其一直向左移动。当32位数字的最左边有1时,它是负数

如何转换回字符串?

执行与从字符串转换相同的操作,但执行相反的操作。右移(和掩码)

为什么要重新发明轮子?来自谷歌:

或者,您可以使用我在这里找到的内容:


您可能还发现此模式很有用:

ip.toLong = function toInt(ip){
  var ipl=0;
  ip.split('.').forEach(function( octet ) {
      ipl<<=8;
      ipl+=parseInt(octet);
  });
  return(ipl >>>0);
};

ip.fromLong = function fromInt(ipl){
  return ( (ipl>>>24) +'.' +
      (ipl>>16 & 255) +'.' +
      (ipl>>8 & 255) +'.' +
      (ipl & 255) );
};
要从此处的源代码获取该功能:


你还可以得到一堆其他的IP实用程序功能。

我稍微修改了Evan的最终答案,特别是dot2num。它的功能相同,但可能更可读,速度稍微慢一些

var aaa = Number("0b"+ "192.168.2.44".split(".").map(
  function(dec){
    return ("00000000" + Number(dec).toString(2)).slice(-8); 
  }).join(""));

aaa.toString(2).match(/.{1,8}/g).map(
  function(bin){
    return Number("0b"+bin); 
  }).join(".");
function ip2num(ip) {
    var parts = ip.split('.');

    var num = 0;
    num += d[0] * Math.pow(2, 24);
    num += d[1] * Math.pow(2, 16);
    num += d[2] * Math.pow(2, 8);
    num += d[3];

    return num;
}

function num2ip(num) {
    var ip = num % 256;

    for (var i=3; i > 0; i--) { 
        num = Math.floor(num / 256);
        ip = num % 256 + '.' + ip;
    }

    return ip;
}

尝试此解决方案,可能会有帮助:

function IpToInteger(ipAddr)
{
    var parts = ipAddr.split('.');
    return (((parts[0] ? parts[0] << 24 : 0) |
             (parts[1] ? parts[1] << 16 : 0) |
             (parts[2] ? parts[2] << 8  : 0) |
             (parts[3])) >>> 0);
}
功能IPointeger(ipAddr)
{
var parts=ipAddr.split('.');
返回(((部件[0]?部件[0]0);
}
取自

常数ip2int=(x)=>(x.split('.')。reduce((a,v)=>((a>>0);
一个衬里:

const ipToLong = ip => ip.split('.').map(parseFloat).reduce((total, part) => total * 256 + part);
用这个

函数num2string(ip){
返回[24,16,8,0]。映射(n=>(ip>>n)&0xff)。连接(“.”)
}
函数string2num(ip){

返回ip.split(“.”)。reduce((sum,x,i)=>sum+(x
((19224)!==192
),因此我不确定它是否可靠。在移位扩展符号时,需要执行位掩码。((192 24)&255)应等于192。@pimvdb@evan或使用多年来一直可用的位无符号右移运算符
>
((192>24)===192
“V4中的IP是32位”==“2^32”==32位数字。有趣的评论,这不是我说的吗?嗯……我一定误解了你说的话。不知道语句末尾的“那个数字”指的是什么。我可能已经“填好了”当我读到它时,我的意思与你的意思不同。非常感谢,这非常有用!我以为javascript总是使用64位有符号浮点,但正如你所说,位移位是在转换为32位有符号整数后执行的。这就是我错的地方!@JPuge不客气!大多数语言尽可能避免浮点。它们'它们的精确度极不精确。它们还需要一种完全不同的处理器(浮点处理器),其中INT只使用加法器/多路复用器和其他非常简单的东西。您的整个IPPoint函数可以替换为:
new Buffer(ip.split(')。readInt32BE(0)
关于Nikolai的解决方案-在某些情况下,这会抛出RangeError(“试图访问超过缓冲区长度”)ip.toLong可能不起作用,因为在forEach循环中的函数执行之前,会返回该值。只需使用一个普通for(int i=0,…)。。。
function IpToInteger(ipAddr)
{
    var parts = ipAddr.split('.');
    return (((parts[0] ? parts[0] << 24 : 0) |
             (parts[1] ? parts[1] << 16 : 0) |
             (parts[2] ? parts[2] << 8  : 0) |
             (parts[3])) >>> 0);
}
function IpAddressToLong(ip){
  return ip.split('.').map((octet, index, array) => {
      return parseInt(octet) * Math.pow(256, (array.length - index - 1));
    }).reduce((prev, curr) => {
      return prev + curr;
  });
}
const ip2int = (x) => (x.split('.').reduce((a, v) => ((a << 8) + (+v)), 0) >>> 0);
const ipToLong = ip => ip.split('.').map(parseFloat).reduce((total, part) => total * 256 + part);