php - php 中的哪个位置实现了 `socket_connect` 迭代为给定主机名返回的多个 IP 地址?

标签 php c sockets glibc

我有这样的代码:

if (!socket_connect($this->sock, $this->host, $this->port)) {

其中 $this->host 是主机名,解析为 2 个 IP 地址。

如果我 strace 这段代码,我会看到类似的内容

1456868407.567615 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
1456868407.567805 fcntl(3, F_GETFL)     = 0x2 (flags O_RDWR)
1456868407.568081 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
1456868407.568264 connect(3, {sa_family=AF_INET, sin_port=htons(5672), sin_addr=inet_addr("192.168.1.111")}, 16) = -1 EINPROGRESS (Operation now in progress)
1456868407.568763 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLIN|POLLOUT|POLLERR|POLLHUP}])
1456868408.724034 getsockopt(3, SOL_SOCKET, SO_ERROR, [111], [4]) = 0
1456868408.724699 fcntl(3, F_SETFL, O_RDWR) = 0
1456868408.725414 close(3)              = 0
1456868408.725901 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
1456868408.726408 fcntl(3, F_GETFL)     = 0x2 (flags O_RDWR)
1456868408.727032 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
1456868408.727727 connect(3, {sa_family=AF_INET, sin_port=htons(5672), sin_addr=inet_addr("192.168.1.112")}, 16) = -1 EINPROGRESS (Operation now in progress)
1456868408.728484 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 1842) = 1 ([{fd=3, revents=POLLOUT}])
1456868408.729281 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
1456868408.729590 fcntl(3, F_SETFL, O_RDWR) = 0

因此,在第一个地址 192.168.1.111 返回 ECONNREFUSED (111) 进行连接后 - php 会尝试下一个地址。

我检查了我正在处理的版本的相应php源代码:https://github.com/php/php-src/blob/php-5.5.9/ext/sockets/sockets.c#L1376,但没有找到它循环的任何地方:

  1. 它通过 if (!php_set_inet_addr(&sin, addr, php_sock TSRMLS_CC)) {

  2. 解析域名
  3. 依次仅设置返回的 hostent 结构中的第一个地址memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry ->h_length); at https://github.com/php/php-src/blob/php-5.5.9/ext%2Fsockets%2Fsockaddr_conv.c#L106

所以我的问题是:相应的代码在哪里实现?

或者不是 php 而是 glibc 这样做的?如果是这样 - 它在 glibc 源代码中的哪里? (我也试图找到那里但失败了)

最佳答案

找到了:https://github.com/php/php-src/blob/php-5.5.9/main/network.c#L797

for (sal = psal; !fatal && *sal != NULL; sal++) {
    sa = *sal;

    /* create a socket for this address */
    sock = socket(sa->sa_family, socktype, 0);

    if (sock == SOCK_ERR) {
        continue;
    }

    // <skipped>

        n = php_network_connect_socket(sock, sa, socklen, asynchronous,
                    timeout ? &working_timeout : NULL,
                    error_string, error_code);

        if (n != -1) { // <-- here is the check
            goto connected;
        }

  // skipped

}

这里它迭代地址,直到可以连接到一个。

关于php - php 中的哪个位置实现了 `socket_connect` 迭代为给定主机名返回的多个 IP 地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35735438/

相关文章:

c++ - 由于 Qt 中的 accept socket 函数,窗口没有出现

node.js - 'adapter' 中没有方法 'io'(node.js、heroku、RedisCloud、socket.io)

php - fatal error 异常: Error: Class 'PDO' not found on symfony2

php - 有没有办法在 Laravel 的模式构建器中为外部约束指定名称?

Php 找不到拆分 utf-8 字符串的方法

c - C 中的函数不返回正确的指针类型?

php - 禁用日期选择器中选定日期的日期

c - fwrite 在每个输入后添加新行

c - 在非规范模式下使用终端 IO 确定按钮边界

php - 无法增加 PHP 中打开的最大文件数