TCP提供可靠的運輸層。它使用的方法之一就是確認從另一端收到的數據。但數據和確認都有可能會丟失。TCP通過在發送時設置一個定時器來解決這種問題。如果當定時器溢出時還沒有收到確認,它就重傳該數據。對任何實現而言,關鍵之處就在於超時和重傳的策略,即怎樣決定超時間隔和如何確定重傳的頻率。
下面我們就着重討論一下超時封裝
</pre><pre code_snippet_id="1654866" snippet_file_name="blog_20160420_2_3554323" name="code" class="cpp">/*
* connect_with_timeout();
*/
int connect_with_timeout(int sock, struct sockaddr *addrs, int adrsLen, struct timeval *tm)
{
int len = sizeof(int);
int flag = 0, retv = 0, err = 0;
fd_set set;
flag = 1;
ioctl(sock, FIONBIO, &flag);
retv = connect(sock, addrs, adrsLen);
if (retv == -1)
{
if (EINPROGRESS == errno)
{
FD_ZERO(&set);
FD_SET(sock, &set);
if (select(sock + 1, NULL, &set, NULL, tm) > 0)
{
getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, (socklen_t*)&len);
if (0 == err)
{
// debug("%s <1>: error=%s\n", __func__, strerror(errno));
retv = 0;
} else
{
// debug("%s <2>: error=%s\n", __func__, strerror(errno));
retv = -1;
}
} else
{
// debug("%s <3>: error=%s\n", __func__, strerror(errno));
retv = -1;
}
}
// debug("%s <4>: error=%s. ret=%d\n", __func__, strerror(errno), retv);
}
flag = 0;
ioctl(sock, FIONBIO, &flag);
return (retv);
}
2.read超時
//read操作加上超時時間。
int read_timeout(int fd, void *buf, uint32_t count, int time)
{
if(time > 0) {
fd_set rSet;
FD_ZERO(&rSet);
FD_SET(fd, &rSet);
struct timeval timeout;
memset(&timeout, 0, sizeof(timeout));
timeout.tv_sec = time;
timeout.tv_usec = 0;
int ret;
while(1) {
ret = select(fd+1, &rSet, NULL, NULL, &timeout);
if(ret < 0) {
if(errno == EINTR) continue;
ERR_EXIT("select");
} else if(ret == 0) {
errno = ETIMEDOUT;
return -1;
} else {
break;
}
}
}
int readNum;
readNum = read(fd, buf, count);
return readNum;
}
3.write超時
int write_timeout(int fd, void *buf, uint32_t count, int time)
{
if(time > 0) {
fd_set wSet;
FD_ZERO(&wSet);
FD_SET(fd, &wSet);
struct timeval timeout;
memset(&timeout, 0, sizeof(timeout));
timeout.tv_sec = time;
timeout.tv_usec = 0;
int ret;
while(1) {
ret = select(fd+1, NULL, &wSet, NULL, &timeout);
if(ret < 0) {
if(errno == EINTR) continue;
ERR_EXIT("select");
} else if(ret == 0) {
errno = ETIMEDOUT;
return -1;
} else {
break;
}
}
}
int writeNum;
writeNum = write(fd, buf, count);
return writeNum;
}