我有一个奇怪的问题,很可能是因为我缺乏套接字编程的经验。
我目前正在使用从socket_last_error()获得的原始错误代码号,因为我看到我需要处理它们。这东西越来越笨重了。
我想使用预定义的常量(无论是我自己的还是内置的)来引用我需要处理的不同类型的套接字错误/条件。
我发现的错误表都使用了相互冲突的值。
在http://php.net/manual/en/sockets.constants.php (在列出原始数字的注释中),我看到如下(摘录):
SOCKET_EINPROGRESS 10036
SOCKET_EALREADY 10037
SOCKET_ENETUNREACH 10051错误的一条注释包含一个列表,其中列出了套接字错误的“标准C定义”(?):
define('EINPROGRESS', 115); /* Operation now in progress */
define('EALREADY', 114); /* Operation already in progress */
define('ENETUNREACH', 101); /* Network is unreachable */ 我自己的系统上的errno.h文件(隐藏在/usr/include/asm-generic/中)似乎支持这一点:
#define EINPROGRESS 115 /* Operation now in progress */
#define EALREADY 114 /* Operation already in progress */
#define ENETUNREACH 101 /* Network is unreachable */然而,这些“标准定义”似乎会根据您所使用的操作系统而改变:BSD4.4号错误.h有以下内容
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
#define ENETUNREACH 51 /* Network is unreachable */现在我们知道了socket_*函数的灵感来源是什么!
最后,我发现在VirtualBox源代码中似乎隐藏着某种解释。
#ifndef EALREADY
# if defined(RT_ERRNO_OS_BSD)
# define EALREADY (37)
# elif defined(RT_OS_LINUX)
# define EALREADY (114)
# else
# define EALREADY (149)
# endif
#endif考虑到这一切..。
socket_last_error() 返回 errno of 101 ,而 Network is unreachable,与51或10051相反。因此,这个函数似乎明显违反了套接字库的官方提供的常量,并且似乎正在使用Linux的错误代码。
(添加了我的答案后进行编辑:上面提到的101是在Linux上获得的。)
所以现在我似乎在没有证件和/或似乎没有定义的行为领域.我现在该干啥?我现在在Linux上;这些值是否曾经改变过?
有什么方法可以使用SOCKET_*常量吗?我当然不介意这样做。
发布于 2017-01-11 00:39:01
听起来你一直在努力研究这个问题--而且平台特有的东西也可能会让人讨厌。让我建议这段代码,它表面上将获取分组为“套接字”常量的所有定义常量:
$consts = get_defined_constants(TRUE);
$socket_constants = $consts["sockets"];
foreach($socket_constants as $key => $value){
echo $key . '=' . $value . "\n";
}在此基础上,我构建了这个函数,您可以在任何平台上找到可能匹配的套接字常量的名称。
function get_socket_constant_names($to_check) {
$consts = get_defined_constants(TRUE);
$socket_constants = $consts["sockets"];
$matches = array();
foreach($socket_constants as $key => $value){
if ($value == $to_check) {
$matches[] = $key;
}
}
return $matches;
}这是:
var_dump(get_socket_constant_names(101));产生这样的结果:
array(1) {
[0] =>
string(18) "SOCKET_ENETUNREACH"
}发布于 2017-01-11 00:14:26
我只是做了些调查。
警告。PHP返回特定于操作系统的套接字错误代码。
我不知道如何检索与socket_*常量兼容的错误代码,因此必须检测OS :'(
见源代码后的证明。
以下是为重点援助而严重忽视的问题。
来自https://github.com/php/php-src/blob/master/ext/sockets/sockets.c
PHP_FUNCTION(socket_connect) {
// will set errno
retval = connect(php_sock->bsd_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
if (retval != 0) {
// call macro defined in php_sockets.h with errno value
PHP_SOCKET_ERROR(php_sock, "unable to connect", errno);
RETURN_FALSE;
}
RETURN_TRUE;
}
PHP_FUNCTION(socket_last_error) {
// check for argument
if (arg1) {
if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) {
RETURN_FALSE;
}
// return errno from passed socket resource
RETVAL_LONG(php_sock->error);
} else {
// return errno from last globally set value
RETVAL_LONG(SOCKETS_G(last_error));
}
}#define PHP_SOCKET_ERROR(socket, msg, errn) \
// store the value for this socket resource
(socket)->error = _err; \
// store the value globally
SOCKETS_G(last_error) = _err证明:
<?php
$s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($s);
socket_connect($s, "google.com", "80");
var_dump(socket_last_error());
var_dump(socket_strerror(socket_last_error()));socket_last_error()**:** 观察的差异
linux$ php asdf.php
int(115)
string(25) "Operation now in progress"
freebsd$ php asdf.php
int(36)
string(25) "Operation now in progress"PHP;DR:在中没有定义的常量列表(我可以看到如何使用这些常量)。您必须提供您自己的操作系统正确的常量列表.
https://stackoverflow.com/questions/41579771
复制相似问题