注:如无特殊说明,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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |