1. 程式人生 > >阻塞通訊模型的網路超時設定

阻塞通訊模型的網路超時設定

阻塞通訊模型的網路超時設定


阻塞通訊模型中,connect、recv、recvfrom、send都是阻塞函式,當不具備條件時,程式會一直阻塞在這些函式呼叫裡,無法執行後續內容。為了解決該問題,可採用非阻塞通訊模型。當然,也可通過設定超時的方法解決阻塞問題。設定超時的方式有兩種,一是利用select;二是利用setsockopt的SO_RCVTIMEO或SO_SNDTIMEO改變socket的屬性。

select

select函式允許呼叫方等待多個事件中一個、多個發生或經歷指定時間後才喚醒它。select可以操作多個不同型別的描述符集合,分別是讀描述符集合、寫描述符集合和異常描述符集合。

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfd_add_1, fd_set * readset, fd_set * writeset, fd_set * exceptset, const struct timeval * timeout)

maxfd_add_1是後續三個描述符集合中最大描述符加1,從0到maxfd_add_1-1的描述符都被檢測。
readset、writeset、exceptset指定核心測試的描述符,無需關注的可設定為NULL。針對fd_set的操作包括:
FD_ZERO(fd_set * fdset) //清空集合
FD_SET(int fd, fd_set * fdset) //將描述符加入集合
FD_ISSET(int fd, fd_set fdset) // 判斷描述符集中的描述符是否滿足I/0條件
FD_CLR(int fd, fd_set

fdset) //將描述符從集合中刪除

struct timeval{
long tv_sec;//seconds
long tv_usec;//microseconds
};
timeout有三種使用方式:
(1)設定為NULL,select會一直阻塞,直至檢測的描述符集中的描述符準備好I/O;
(2)將tv_sec和tv_usec都設定為0,select不等待,檢測描述符後直接返回;
(3)將tv_sec或tv_usec設定為大於0的數,等待指定時間,直至描述符準備好I/O或已到等待期限;

setsockopt

設定套接字的選 項。選項可能存在於多層協議中,它們總會出現在最上面的套接字層。當操作套接字選項時,選項位於的層和選項的名稱必須給出。為了操作套接字層的選項,應該將層的值指定為SOL_SOCKET。為了操作其它層的選項,控制選項的合適協議號必須給出。例如,為了表示一個選項由TCP協議解析,層應該設定為協議 號TCP。
#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

引數:
sock:將要被設定或者獲取選項的套接字。
level:選項所在的協議層。
optname:需要訪問的選項名。
optval:對於getsockopt(),指向返回選項值的緩衝。對於setsockopt(),指向包含新選項值的緩衝。
optlen:對於getsockopt(),作為入口引數時,選項值的最大長度。作為出口引數時,選項值的實際長度。對於setsockopt(),現選項的長度。

SO_RCVTIMEO和SO_SNDTIMEO分別用來設定socket接收資料和傳送資料的超時時間,僅對資料接收和傳送相關的socket函式有效,這些函式包括 send,sendmsg,recv,recvmsg ,accept 和connect。針對不同的函式,超時後設定的errno不同。
在這裡插入圖片描述

設定描述符超時:
socklen_t optlen = sizeof(struct timeval);
struct timeval tv;
tv.tv_sec = 10800;
tv.tv_usec = 0;
setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen);

select與setsockopt設定超時的區別

(1)setsockopt是修改套接字的屬性,select是判斷是否能進行某種操作,滿足I/O條件後再呼叫阻塞函式;
(2)setsockopt只要設定一次即可;select是在阻塞函式前呼叫,每次呼叫阻塞函式前都需要先呼叫select;
(3)select同時操作多個描述符;
(4)setsockopt精度是毫秒級;select可設定更高的精度(微秒級);