假设012.012.012.012等IPv4地址表示中有前导零。
为了消除前导零,我只需编写以下代码,它就像我在Mac上预期的那样工作:
% php -r 'var_dump(long2ip(ip2long("012.012.012.012")));'
Command line code:1:
string(11) "12.12.12.12"
% php --version
PHP 7.3.25 (cli) (built: Dec 25 2020 22:03:38) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.25, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.25, Copyright (c) 1999-2018, by Zend Technologies
with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans但这段简单的代码在CentOS 7上不起作用,它看起来像是ip2long("012.012.012.012")返回false值:
$ php -r 'var_dump(long2ip(ip2long("012.012.012.012")));'
string(7) "0.0.0.0"
$ php --version
PHP 7.3.25 (cli) (built: Nov 24 2020 11:10:55) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.25, Copyright (c) 1998-2018 Zend Technologies
$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)这两个PHP版本是相同的,我希望它们返回完全相同的值。我还阅读了ip2long docs,并尝试查找是否有针对此行为的特殊选项/配置,但没有成功。
有人能给我指引正确的方向吗?是什么让它们不同?我该怎么做呢?
发布于 2021-01-15 19:10:46
好了,我找到了罪魁祸首。在LLVM和GCC之间不同的inet_pton(3)实现导致了这种行为,就像Russ-san commented一样。6年前也有关于完全相同的问题的a bug report。根据this patch的说法,似乎PHPV5.2.10已经开始使用inet_pton而不是inet_addr,这就是为什么older versions of PHP将每个块视为八进制。
test.c
#include <stdio.h>
#include <arpa/inet.h>
#define INADDR "012.012.012.012"
int main() {
struct in_addr inaddr;
if (inet_pton(AF_INET, INADDR, &inaddr) == 0) {
printf("Invalid: %s\n", INADDR);
}
else {
printf("Valid: %s\n", INADDR);
}
return 0;
}% cc test.cc && ./a.out
Valid: 012.012.012.012$ cc test.cc && ./a.out
Invalid: 012.012.012.012我放弃了使用ip2long / long2ip内置函数,现在尝试使用https://github.com/mlocati/ip-lib
>>> \IPLib\Address\IPv4::fromString("1.2.3.12")->toString(true);
=> "001.002.003.012"
>>> \IPLib\Address\IPv4::fromString("001.002.003.012")->toString();
=> "1.2.3.12"到目前为止还没有问题。
https://stackoverflow.com/questions/65719480
复制相似问题