linux 網絡編程基礎(四)read,write,connect超時封裝

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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章