天天看點

67-套接字逾時(select)

設定逾時的第二個技術是使用 select 函數。它使用了 select 函數的最後一個逾時參數,對套接字描述符進行了“預讀”。

1. 程式路徑

如果你已經 clone 過這個代碼了,請使用 Git pull 更新一下。本節程式所使用的程式路徑是 ​

​unp/program/advcio/read_timeo/read_timeo_select​

​.

2. 僞代碼

  • 用于判斷是否可讀的函數
// 該函數利用 select 函數判斷在 nsec 時間内描述符 fd 是否可讀
int readable_timeo(int fd, int nsec) {
  int
  fd_set rfds;
  struct timeval tv;

  FD_ZERO(&rfds);
  FD_SET(fd, &rfds);

  tv.tv_sec = nsec;
  tv.tv_usec = 0;

  ret = select(fd + 1, &rfds, NULL, NULL, &tv);      
  • 帶逾時的 recvfrom 函數
int recvfrom_timeo(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen, int nsec) {
  int ret;

  ret = readable_timeo(sockfd, nsec);

  // select 函數傳回 0,表示逾時
  if (ret == 0) {
    errno = ETIMEDOUT;
    ret = -1;
  }
  else {
    ret = recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
  }

  return      

3. 實驗結果

read_timeo_select 是一個 udp 用戶端,實際上就是前面的 udp/basic 程式,隻不過它将 recvfrom 修改成了帶逾時的 recvfrom.

read_timeo_select 向 mars 主機發送了一個封包後,阻塞在 recvfrom_timeo 函數上,因為 mars 主機上的伺服器并未啟動,是以 read_timeo_select 永遠也不可能收到 mars 主機發回的資料。

經曆 5 秒的時候後,recvfrom_timeo 函數逾時傳回。

67-套接字逾時(select)

4. 總結

  • 掌握使用 select 函數編寫逾時函數的方法