首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找正确的PHP套接字错误常量

问寻找正确的PHP套接字错误常量
EN

Stack Overflow用户
提问于 2017-01-10 22:44:23
回答 2查看 1.5K关注 0票数 3

我有一个奇怪的问题,很可能是因为我缺乏套接字编程的经验。

我目前正在使用从socket_last_error()获得的原始错误代码号,因为我看到我需要处理它们。这东西越来越笨重了。

我想使用预定义的常量(无论是我自己的还是内置的)来引用我需要处理的不同类型的套接字错误/条件。

我发现的错误表都使用了相互冲突的值。

在http://php.net/manual/en/sockets.constants.php (在列出原始数字的注释中),我看到如下(摘录):

代码语言:javascript
复制
SOCKET_EINPROGRESS        10036
SOCKET_EALREADY           10037
SOCKET_ENETUNREACH        10051

错误的一条注释包含一个列表,其中列出了套接字错误的“标准C定义”(?):

代码语言:javascript
复制
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/中)似乎支持这一点:

代码语言:javascript
复制
#define EINPROGRESS     115     /* Operation now in progress */
#define EALREADY        114     /* Operation already in progress */
#define ENETUNREACH     101     /* Network is unreachable */

然而,这些“标准定义”似乎会根据您所使用的操作系统而改变:BSD4.4号错误.h有以下内容

代码语言:javascript
复制
#define EINPROGRESS 36      /* Operation now in progress */
#define EALREADY    37      /* Operation already in progress */
#define ENETUNREACH 51      /* Network is unreachable */

现在我们知道了socket_*函数的灵感来源是什么!

最后,我发现在VirtualBox源代码中似乎隐藏着某种解释。

代码语言:javascript
复制
#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_*常量吗?我当然不介意这样做。

EN

回答 2

Stack Overflow用户

发布于 2017-01-11 00:39:01

听起来你一直在努力研究这个问题--而且平台特有的东西也可能会让人讨厌。让我建议这段代码,它表面上将获取分组为“套接字”常量的所有定义常量:

代码语言:javascript
复制
$consts = get_defined_constants(TRUE);
$socket_constants = $consts["sockets"];
foreach($socket_constants as $key => $value){
    echo $key . '=' . $value . "\n";
}

在此基础上,我构建了这个函数,您可以在任何平台上找到可能匹配的套接字常量的名称。

代码语言:javascript
复制
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;
}

这是:

代码语言:javascript
复制
var_dump(get_socket_constant_names(101));

产生这样的结果:

代码语言:javascript
复制
array(1) {
  [0] =>
  string(18) "SOCKET_ENETUNREACH"
}
票数 2
EN

Stack Overflow用户

发布于 2017-01-11 00:14:26

我只是做了些调查。

警告。PHP返回特定于操作系统的套接字错误代码。

我不知道如何检索与socket_*常量兼容的错误代码,因此必须检测OS :'(

见源代码后的证明。

以下是为重点援助而严重忽视的问题。

来自https://github.com/php/php-src/blob/master/ext/sockets/sockets.c

代码语言:javascript
复制
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));
    }
}

来自sockets.h

代码语言:javascript
复制
#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

证明:

代码语言:javascript
复制
<?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()**:** 观察的差异

代码语言:javascript
复制
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:在中没有定义的常量列表(我可以看到如何使用这些常量)。您必须提供您自己的操作系统正确的常量列表.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41579771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档