c/c :gethostbyname 同主机同域名有时阻塞有时立刻错误返回-尊龙官方平台

c/c :gethostbyname 同主机同域名有时阻塞有时立刻错误返回

el/2024/3/25 16:50:02

c/c :gethostbyname 同主机同域名有时阻塞有时立刻错误返回

最近项目中遇到一个很奇特的问题:

在同一主机上,gethostbyname 调用,对同一域名进行查询出现两种情况:

1.阻塞一段时间,然后失败返回;

2.不阻塞,立刻失败返回。

虽然都是失败,但为什么有时候会阻塞,有时候立刻返回失败?

我们知道,gethostbyname 是可能阻塞向域名服务器发送 dns query 请求获取目的信息。

通常,gethostbyname 将按照 /etc/nsswitch.conf 定义的顺序依次查询。

man /etc/nsswitch.conf:
hosts  host names and numbers, used by gethostbyname(3) and similar functions.)

例如,我的 /etc/nsswitch.conf 定义的关于 hosts 查询顺序为:

[test1280@localhost ~]$ grep hosts /etc/nsswitch.conf | grep "^[^#]"
hosts:      files dnsps:
files = /etc/hosts/
dns   = /etc/resolv.conf

/etc/hosts:

这个文件是个静态映射表,将主机名映射到ip地址。

[root@localhost ~]# cat /etc/hosts
127.0.0.1	localhost.localdomain	localhost
::1	localhost6.localdomain6	localhost6

/etc/resolv.conf:

这个文件是 resolver 的配置文件。记录的是多个 dns 域名服务器 ip 地址。

当我们需要进行 dns 查询时,将依次向这个文件指向的 dns 域名服务器发送 dns query 请求获取信息。

[root@localhost ~]# cat /etc/resolv.conf 
# generated by networkmanager
domain localdomain
search localdomain
nameserver 192.168.40.2

而 /etc/nsswitch.conf 配置中 hosts 一项则定义,当我查询域名 “abc” 时的查询顺序。

按照我上面的配置,先 files 后 dns,也就是说:

1.尝试从 /etc/hosts 中查询 abc 对应的 ip 地址,如果有直接返回成功,否则2;
2.尝试从 /etc/resolv.conf 中指向的 dns(从上到下依次尝试【nameserver】) 查询 abc,如果找到直接返回成功,否则返回失败。

demo:

main.c:#include 
#include 
#include 
#include 
#include extern int h_errno;int main(int argc, char **argv)
{char *hostname = argc < 2 ? "test1280.jlnu.edu" : argv[1];printf("gethostbyname start:%ld\n", time(null));struct hostent *h = gethostbyname(hostname);printf("gethostbyname end  :%ld\n", time(null));if (h == null){printf("gethostbyname(%s) error(%s)\n", hostname, hstrerror(h_errno));exit(2);}printf("gethostbyname(%s) ok: %p\n", hostname, h);exit(0);
}

当我在 root 下执行:

[root@localhost ~]# ./main abc
gethostbyname start:1538821042
gethostbyname end  :1538821052
gethostbyname(abc) error(host name lookup failure)

失败,阻塞 10 秒返回。

当我在普通用户 test1280 下执行:

[test1280@localhost ~]$ ./main abc
gethostbyname start:1538821147
gethostbyname end  :1538821147
gethostbyname(abc) error(host name lookup failure)

失败,立刻返回。

到这一步其实已经可以有点联想啦!(虽然当时我并没有…)

我们尝试抓包看看!

abc 这个域名在 /etc/hosts 中没有映射规则,正常来说为获取这个域名信息,将会有 dns 查询发生。

我的 /etc/resolv.conf 的 nameserver 仅一个:192.168.40.2

tcpdump -i eth0 host 192.168.40.2 -s 0 -w dns.cap

1)在 root 下抓包,在 root 下执行 main:

2)在 root 下抓包,在 test1280 下执行 main:啥也没抓到。

即,在 test1280 账户中执行 main 调用 gethostbyname,没有发生 dns 查询。

因为,/etc/resolv.conf 对于普通用户 test1280 没有读权限!

[root@localhost ~]# ll /etc/resolv.conf 
-rw-r-----. 1 root root 92 oct  6 02:33 /etc/resolv.conf

对于超级用户 root,执行 gethostbyname 时,底层实现以 root 身份打开此配置文件获取 dns ip 地址,然后发送 dns query,阻塞等待查询结果返回。

对于普通用户 test1280,执行 gethostbyname 时,底层实现无法以 test1280 身份打开此配置文件获取 dns ip 地址,于是直接失败返回,没有执行 dns 查询。

当我给 /etc/resolv.conf 添加任意用户读权限后,在 test1280 账户执行 main 程序将会阻塞一段时间失败返回,并可抓到 dns query 包。


http://www.ngui.cc/el/5127083.html

相关文章

xshell:登陆执行脚本(命令)【ssh自动多级跳转】

xshell:登陆执行脚本(命令)【ssh自动多级跳转】 使用xshell在登陆到服务器时,可以配置需要自动执行的命令。 最常用的是,我们可以使用此特性完成ssh自动多级跳转。 通常,现网生产环境是和不能通过公网直…

git:源码安装版本控制工具git

git:源码安装版本控制工具git 1.下载源码 https://github.com/git/git https://www.git-scm.com/download/ https://mirrors.edge.kernel.org/pub/software/scm/git/我下载的源码是: https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.20.…

go: go mod获取第三方依赖包unknown revision xxx错误解决

go: go mod获取第三方依赖包unknown revision xxx错误解决 使用go mod处理第三方依赖包时出现unknown revision xxx错误,解决方法如下: 以go-chassis为例: [test1280localhost ~]$ git clone https://github.com/go-chassis/go-chassis.gi…

linux:获取线程的pid(tid、lwp)的几种方式

linux:获取线程的pid(tid、lwp)的几种方式 在 linux c/c 中通常是通过 pthread 库进行线程级别的操作。 在 pthread 库中有函数: pthread_t pthread_self(void);它返回一个 pthread_t 类型的变量,指代的是调用 pthr…

linux:taskset 查询或设置进程(线程)绑定cpu(亲和性)

linux:taskset 查询或设置进程(线程)绑定cpu(亲和性) 通过 taskset 命令可将某个进程与某个cpu核心绑定,使得其仅在与之绑定的cpu核心上运行。 线程是最小的内核执行调度单元,因此,…

linux:查看线程运行于哪个cpu核心上

linux:查看线程运行于哪个cpu核心上 线程是最小的执行调度单元,线程执行于某个cpu核心之上,或者说某个cpu核心执行此线程。 如何查看某线程运行于哪个cpu核心上呢? 方法一:ps -elf 查找 psr 字段值 [test1280localh…

linux:获取、设置进程(线程)的cpu亲和性

linux:设置进程(线程)的cpu亲和性 一、进程的cpu亲和性的获取(get)或者设置(set) int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); int sched_getaffinity(pid_t pid,…

go:go-chassis 第三方依赖包问题

go:go-chassis 第三方依赖包问题 1.下载 go-chassis 源码 test1280 $ git clone https://github.com/go-chassis/go-chassis initialized empty git repository in /home/test1280/go-chassis/.git/ remote: enumerating objects: 53, done. remote: counting obj…

git:fatal: unable to find remote helper for 'https'

git:fatal: unable to find remote helper for ‘https’ 复现 test1280 $ git clone https://github.com/go-chassis/go-chassis cloning into go-chassis... fatal: unable to find remote helper for httpstest1280 $ echo $path /home/test1280/git/bin:/home…

c:strerror(或 inet_ntoa) 返回值默认整型截断导致进程核心转储 core dumped

c:strerror(或 inet_ntoa) 返回值默认整型截断导致进程核心转储 core dumped 测试环境: [test1280localhost ~]$ uname -a linux localhost.localdomain 2.6.32-642.el6.x86_64 #1 smp tue may 10 17:27:01 utc 2016 x86_64 x86…
网站地图