为什么SO_RCVTIMEO超时后设置不同?

时间:2017-03-01 16:25:14

标签: c linux sockets tcp

我在Fedora 25上。在下面的测试程序中,我将recv timeout设置为12秒,12345 microsec,setsockopt。但是当我使用getsockopt获得超时值时,我得到的值略有不同:12秒,13000微秒。我希望它与setsockopt设置的相同。

为何与众不同?

[ ~]$ cat sockopt.c
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>

int main()
{
    int sd = socket(AF_INET, SOCK_STREAM, 0);
    int rc;
    struct timeval tv;
    socklen_t len = sizeof(tv);

    tv.tv_sec = 12;
    tv.tv_usec = 12345;
    rc = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    if (rc < 0) printf("oops\n");

    rc = getsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len);
    if (rc < 0) printf("oops\n");
    printf("%ld, %ld\n",  tv.tv_sec, tv.tv_usec);
}
[ ~]$ 
[ ~]$ gcc -Wall sockopt.c
[ ~]$ 
[ ~]$ ./a.out 
12, 13000
[ ~]$ 

1 个答案:

答案 0 :(得分:0)

根据内核sources:设置printf %q时,将# ask your shell to generate an eval-safe quoted form of your argument list printf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd' # ...and use bash to evaluate that quoted form. ssh josh-play 'exec bash -s' <<<"$rmt_cmd" 转换为SO_RCVTIMEO值,对struct tv值使用算术。另一方面,在检索long值时,HZ值由SO_RCVTIMEO构成。因此,结果取决于时间分辨率(struct tv值),以及算术除法和模数。