IP-addresses stored as int results in overflow?

2020-05-25 06:26发布

I'm writing a chat-server in node.js, and I want to store connected users IP-addresses in a mysql database as (unsigned) integers. I have written a javascript method to convert an ip-address as string to an integer. I get some strange results however.

Here is my code:

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;
}

When I run call the method as ipToInt("192.168.2.44"); the result I get is -1062731220. It seems like an overflow has occurred, which is strange, because the expected output (3232236076) is inside the number range in javascript (2^52).

When I inspect -1062731220 in binary form, I can see the 3232236076 is preserved, but filled with leading 1's.

I'm not sure, but I think the problem is with signed vs. unsigned integers.

Can any of you explain what is going on? And possibly how to parse -1062731220 back to an string ip?

标签: javascript
11条回答
Animai°情兽
2楼-- · 2020-05-25 07:02

You shifted left to get the original number - which is just 4 sets of bits regardless of the sign.

Shift right to get back to the IP. Doesn't matter what the sign is.

查看更多
放荡不羁爱自由
3楼-- · 2020-05-25 07:03

I revised Evan's final answer a bit, particularly dot2num. It functions the same but might be more readable and is marginally slower.

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;
}
查看更多
闹够了就滚
4楼-- · 2020-05-25 07:05

The result of the "<<" operator is always a signed, 32-bit integer, as per the spec.

When you shift back, use ">>>" to do an unsigned right shift.

查看更多
家丑人穷心不美
5楼-- · 2020-05-25 07:09
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(".");
查看更多
你好瞎i
6楼-- · 2020-05-25 07:09
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;
  });
}

Taken from repo

查看更多
登录 后发表回答