注:如无特殊说明,sockfd 原始状态都是阻塞的。
一、使用alarm 函数设置超时
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 |
void handler(
int sig)
{ } signal(SIGALRM, handler); alarm( 5); int ret = read(fd, buf, sizeof(buf)); if (ret == - 1 && errno == EINTR) errno = ETIMEOUT; else if (ret >= 0) alarm( 0); ................. |
程序大概框架如上所示,如果read在5s内被SIGALRM信号中断而返回,则表示超时,否则未超时已读取到数据,取消闹钟。但这种方法不常用,因为有时可能在其他地方使用了alarm会造成混乱。
二、使用套接字选项SO_SNDTIMEO、SO_RCVTIMEO
C++ Code
1
2 3 4 5 6 |
struct timeval timeout = {3,0};
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO
, (char *)&timeout, sizeof(struct timeval));
int ret = read(sock, buf, sizeof(buf)); if (ret == - 1 && errno == EWOULDBLOCK) errno = ETIMEOUT; .......... |
即使用setsockopt 函数进行设置,但这种方法可移植性比较差,不是每种系统实现都有这些选项。
三、使用select 实现超时
下面程序包含read_timeout、write_timeout、accept_timeout、connect_timeout 四个函数封装
C++ Code
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |