题目:11.11 如果找不到给定 IP 地址对应的主机名,gethostbyaddr 可能就得花很长时间(最长 80s)才能返回一个错误.编写一个新的名为 getnameinfo_timeo 的函数,它有一个额外的整数参数用于指定等待应答的最大秒数.如果发生超时并且没有设置 NI_NAMEREQD 标志,那就调用 inet_ntop 返回一个地址串.
我的问题是如何实现 timeout 功能?
我的问题是如何实现 timeout 功能?
1
seaswalker May 1, 2018 via iPhone
猜一下,定时器?
|
2
XiaoxiaoPu May 1, 2018 简单的方法就是多线程呗,起一个线程去调用 gethostbyaddr,主线程等待 timeout,超时了就把子线程杀掉,然后返回
|
3
geelaw May 1, 2018 如果你用纯粹的 UNIX,似乎只有比较低效的方式,而且很容易受其他正在运行的子进程的干扰。
思路是这样的:fork 两个子进程,一个等待 timeout 那么多秒,另一个调用 gethostbyaddr,并尝试把结果告诉主进程(共享内存或者匿名管道),主进程用 wait,在其中一个子进程结束的时候就可以返回,所以是 whichever comes first,接下来可以杀掉另一个子进程并根据结果返回。 问题:如果调用这个东西之前 fork 出来了子进程,那么 wait 可能会拿到不是你控制(创建)的子进程的结果。 如果你的环境支持比 POSIX 更多的 API set,你可以尝试使用 WaitForMultipleObjectsEx 的等价物。 |
4
chashao OP @geelaw 我看书 301 页对于 connect 的设置超时代码,能不能换成 gethostbyaddr
```c static void getnameinfo_alarm(int signo) { return; } int getnameinfo_timeo(const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flag, int timeout){ Sigfunc *sigfunc; sigfunc = Signal(SIGALRM, getnameinfo_alarm); if (alarm(timeout) != 0) { err_msg("alarm is aready set!"); } int ret; if ((ret = getnameinfo(sockaddr, addrlen, host, hostlen, serv, servlen, flag)) != 0) { printf("getnameinfo error:%s", gai_strerror(ret)); } alarm(0); Signal(SIGALRM, sigfunc); return ret; } ``` |
5
geelaw May 1, 2018 重新翻了一下 - - 发现有 waitpid,那一个土鳖的方法是循环 waitpid WNOHANG + sleep 直到超时到了。并没想过用 signal/alarm。
|