超時設置

//read操作加上超時時間。1 int read_timeout(int fd, void *buf, uint32_t count, int time)
 2 {
 3     if(time > 0) {
 4         fd_set rSet;
 5         FD_ZERO(&rSet);
 6         FD_SET(fd, &rSet);
 7 
 8         struct timeval timeout;
 9         memset(&timeout, 0, sizeof(timeout));
10         timeout.tv_sec = time;
11         timeout.tv_usec = 0;
12         
13         int ret;
14         while(1) {
15             ret = select(fd+1, &rSet, NULL, NULL, &timeout);
16             if(ret < 0) {
17                 if(errno == EINTR) continue;
18                 ERR_EXIT("select");
19             } else if(ret == 0) {
20                 errno = ETIMEDOUT;
21                 return -1;
22             } else {
23                 break;
24             }
25         }
26     }
27     int readNum;
28     readNum = read(fd, buf, count);
29     return readNum;
30 }

寫超時

 1 int write_timeout(int fd, void *buf, uint32_t count, int time)
 2 {
 3     if(time > 0) {
 4         fd_set wSet;
 5         FD_ZERO(&wSet);
 6         FD_SET(fd, &wSet);
 7 
 8         struct timeval timeout;
 9         memset(&timeout, 0, sizeof(timeout));
10         timeout.tv_sec = time;
11         timeout.tv_usec = 0;
12         
13         int ret;
14         while(1) {
15             ret = select(fd+1, NULL, &wSet, NULL, &timeout);
16             if(ret < 0) {
17                 if(errno == EINTR) continue;
18                 ERR_EXIT("select");
19             } else if(ret == 0) {
20                 errno = ETIMEDOUT;
21                 return -1;
22             } else {
23                 break;
24             }
25         }
26     }
27     int writeNum;
28     writeNum = write(fd, buf, count);
29     return writeNum;
30 }

accept超時操作

int accept_timeout(int fd, struct sockaddrin *addr, socklen_t *addrlen, int time)
{
  int ret;
  if(time > 0) {
    fd_set rSet;
    FD_ZERO(&rSet);
    FD_SET(fd, &rSet);    struct timeval timeout;
    timeout.tv_sec = time;
    timeout.tv_usec = 0;    int selectRet;
    do {
      selectRet = select(fd + 1, &rSet, NULL, NULL, &timeout);
    }while(selectRet < 0 && selectRet == EINTR);
    if(selectRet < 0 ) {
      return -1;
    } else if(selectRet == 0) {
      errno = ETIMEDOUT;
      return -1;
    }	
  }
  if(addr) {
    ret = accept(fd, (struct sockaddr *)addr, addrlen);
  } else {
    ret = accept(fd, NULL, NULL);
  }
  return ret;
}

檢測監聽套接字是否可讀,當監聽套接字可讀的時候,就認為連接隊列發生了連接。

connect

 1 void setNonBlockMode(int fd)
 2 {
 3     int flags = fcntl(fd, F_GETFL);
 4     if(flags < 0) {
 5         ERR_EXIT("fcntl");
 6     }
 7     flags |= O_NONBLOCK;
 8     if(fcntl(fd, F_SETFL, flags) < 0) {
 9         ERR_EXIT("fcntl");
10     }
11 }
12 
13 void setBlockMode(int fd)
14 {
15     int flags = fcntl(fd, F_GETFL);
16     if(flags < 0) {
17         ERR_EXIT("fcntl");
18     }
19     flags &= ~O_NONBLOCK;
20     if(fcntl(fd, F_SETFL, flags) < 0) {
21         ERR_EXIT("fcntl");
22     }
23 
24 }
25 
26 int connect_timeout(int sockfd, struct sockaddrin *addr, socklen_t addrlen, int time)
27 {
28     int ret = -1;
29 
30     if(time > 0) {
31         setNonBlockMode(sockfd);
32     }    
33     ret = connect(sockfd, (struct sockaddr*)addr, addrlen);
34     if(ret < 0 && errno == EINPROGRESS) {
35         fd_set wSet;
36         FD_ZERO(&wSet);
37         FD_SET(sockfd, &wSet);
38         
39         struct timeval timeout;
40         timeout.tv_sec = time;
41         timeout.tv_usec = 0;
42         
43         int selcetRet;
44         do{
45             selcetRet = select(sockfd + 1, NULL, &wSet, NULL, &timeout);
46         }while(selcetRet < 0 && errno == EINTR);
47         if(selcetRet < 0) {
48             ret = -1;
49         } else if(selcetRet == 0) {
50             ret = -1;
51             errno = ETIMEDOUT;
52         } else if(selcetRet > 0) {
53             int err;
54             socklen_t socklen = sizeof(err);
55             int sockoptRet = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen);
56             if(sockoptRet == -1) {
57                 ret = -1;
58             } 
59             if(err == 0) {
60                 ret = 0;
61             } else {
62                 errno = err;
63                 ret = -1;
64             }
65         }
66     }
67     if(time > 0) {
68         setBlockMode(sockfd);
69     }
70     return ret;
71 }

1.設置fd為非阻塞模式。

2.調用connect操作,如果網絡條件很好,比如本機兩個socket發生連接,會發生成功返回。

3.正常情況下,connect立即返回-1并設置errno為EINPROGRESS 表示正在連接過程中。

4.使用select檢測fd是否可寫。 如果檢測到可寫也有如下兩種情況:

1. connect連接成功。

2. 產生了錯誤,我們就需要用getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen); 來判斷是否發生了錯誤。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383191.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383191.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383191.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

字符串題目 1 --------判斷兩個字符串是否為旋轉詞

題目描述 如果一個字符串為str&#xff0c;把字符串的前面任意部分挪到后面形成的字符串交str的旋轉詞。比如str“12345”&#xff0c;str的旋轉串有“12345”、“45123”等等。給定兩個字符串&#xff0c;判斷是否為旋轉詞。 輸入描述: 輸出包含三行&#xff0c;第一個兩個…

2021-03-04

為什么nginx轉發后端默認使用1.0而不是1.1 在 Nginx 的官網文檔中&#xff0c;有這樣一個指令&#xff1a; Syntax: gzip_http_version 1.0 | 1.1; Default: gzip_http_version 1.1; Context: http, server, location Sets the minimum HTTP version of a request required to…

字符串題目---2判斷兩個字符串是否為變形詞

題目描述 給定兩個字符串str1和str2&#xff0c;如果str1和str2中出現的字符種類出現的一樣且每種字符出現的次數也一樣&#xff0c;那么str1和str2互為變形詞。請判斷str1和str2是否為變形詞 輸入描述: 輸入包括3行&#xff0c;第一行包含兩個整數n&#xff0c;m(1 \leq n,…

設計模式7----代理模式

代理模式 概念 Proxy 模式又叫做代理模式&#xff0c;是結構型的設計模式之一&#xff0c;它可以為其他對象提供一 種代理&#xff08;Proxy&#xff09;以控制對這個對象的訪問。 所謂代理&#xff0c;是指具有與代理元&#xff08;被代理的對象&#xff09;具有相同的接口的…

網絡基礎3-1(細談IP協議頭, 網絡層,子網劃分,路由選擇,數據鏈路層,以太網幀格式,MAC地址,再談ARP協議)

IP協議 IP協議頭格式 4位版本號(version): 指定IP協議的版本, 對于IPv4來說, 就是44位頭部長度(header length): IP頭部的長度是多少個。32bit, 也就是 length * 4 的字節數. 4bit表示大 的數字是15, 因此IP頭部大長度是60字節8位服務類型(Type Of Service): 3位優先權字段(已…

c++常見并且必須記住的問題

一、基礎知識 基本語言 1、說一下static關鍵字的作用 ?2、說一下C和C的區別 3、說一說c中四種cast轉換 4、請說一下C/C 中指針和引用的區別&#xff1f; 5、給定三角形ABC和一點P(x,y,z)&#xff0c;判斷點P是否在ABC內&#xff0c;給出思路并手寫代碼 6、怎么判斷一個…

網絡中典型協議--(DNS,輸入url后, 發生的事情. ,ICMP,NAT)

DNS&#xff08;Domain Name System&#xff09; DNS是一整套從域名映射到IP的系統 域名服務器發展背景 TCP/IP中使用IP地址和端口號來確定網絡上的一臺主機的一個程序. 但是IP地址不方便記憶. 于是人們發明了一種叫主機名的東西, 是一個字符串, 并且使用hosts文件來描述主機…

高級IO--1 ---(五種典型IO,阻塞IO,非阻塞IO,信號驅動IO,異步IO, IO多路轉接)

高級IO&#xff1a; 五種典型IO&#xff1a; 阻塞IO/非阻塞IO/信號驅動IO/異步IO/IO多路轉接 IO多路轉接模型&#xff1a;select/poll/epoll 五種典型IO 阻塞IO IO操作的流程&#xff1a;等待IO操作條件具備&#xff0c;然后進行數據拷貝 為了完成IO操作發起調用&#xff…

IO多路轉接模型----(select的模型,select的優缺點,poll的模型,poll的優缺點)

IO多路轉接模型&#xff1a;select/poll/epoll 對大量描述符進行事件監控(可讀/可寫/異常) select模型 用戶定義描述符的事件監控集合 fd_set&#xff08;這是一個位圖&#xff0c;用于存儲要監控的描述符&#xff09;; 用戶將需要監控的描述符添加到集合中&#xff0c;這個描…

IO多路轉接模型-----epoll

epoll&#xff1a; Linux下性能最高的多路轉接模型 epoll 有3個相關的系統調用. epoll_create 功能&#xff1a;創建epoll&#xff0c;在內核中創建eventpoll結構體&#xff0c;size決定了epoll最多監控多少個描述符&#xff0c;在Linux2.6.8之后被忽略&#xff0c;但是必須…

再寫順序表(c語言實現,外加冒泡排序,二分查找)

概念 順序表是用一段物理地址連續的存儲單元依次存儲數據元素的線性結構&#xff0c;一般情況下采用數組存儲。在數組 上完成數據的增刪查改。 順序表一般可以分為&#xff1a; 靜態順序表&#xff1a;使用定長數組存儲。動態順序表&#xff1a;使用動態開辟的數組存儲。 頭…

再寫單鏈表(不帶頭單鏈表)

單鏈表 實際中鏈表的結構非常多樣&#xff0c;以下情況組合起來就有8種鏈表結構&#xff1a; 單向、雙向帶頭、不帶頭循環、非循環 雖然有這么多的鏈表的結構&#xff0c;但是我們實際中最常用還是兩種結構&#xff1a; 無頭單向非循環鏈表&#xff1a;結構簡單&#xff0…

再寫雙向循環鏈表

#pragma once #include<assert.h> #include<malloc.h> #include<stdio.h> typedef int DLDataType;//定義鏈表結點結構 typedef struct DListNode{DLDataType value;struct DListNode *prev; //指向前一個結點struct DListNode *next; //指向后一個結點 } DL…

鏈表題目--1 刪除鏈表中所有等于val的值

注意事項 要刪除的結點相鄰第一個結點就是要刪除的結點 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* removeElements(struct ListNode* head, int val){if(headNULL){return NULL;}struct …

鏈表題目--2 求鏈表的中間結點 和 求鏈表中倒數第k個結點

求鏈表的中間結點 思路 一個走兩步&#xff0c;一個走一步。一個走到尾&#xff0c;另外一個就走到了中間 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* middleNode(struct ListNode* head…

鏈表題目---3 合并兩個有序單鏈表 和 分割鏈表

合并兩個有序單鏈表 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){if(l1 NULL){return l2;}else if(l2 NULL){return l1;}struc…

鏈表題目---4 刪除鏈表中重復的結點 和 判斷鏈表是否為回文鏈表

刪除鏈表中重復的結點 /* struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {} }; */ class Solution { public:ListNode* deleteDuplication(ListNode* pHead){if(pHead NULL){return NULL;}ListNode *prev NULL; //用于刪除的結點, 是…

鏈表題目----5 相交鏈表 和 環形鏈表 和 返回鏈表開始入環的第一個節點

相交鏈表 思路 鏈表交叉不可能是x型因為有可能兩個鏈表不等長&#xff0c;所以我們必須讓他們從同一起跑位置去起跑從同一起跑位置出發&#xff0c;依次比較每個結點的地址是否相同 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct L…

鏈表題目---6 復制帶隨機指針的鏈表

思路 將新結點放在老結點的后面 復制random 將鏈表拆開 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node() {}Node(int _val, Node* _next, Node* _random) {val _val;next _next;random _random;} }; */ class Solution { publi…

括號匹配問題(c和c++版本實現)

括號匹配問題 思路 遇見左括號入棧&#xff0c;遇見一個右括號彈出棧頂元素右括號入棧前如果棧已經為空&#xff0c;則不匹配如果不為空則讀取并彈出&#xff0c;彈出來的元素與右括號做比較&#xff0c;必須匹配&#xff0c;不匹配返回false;如果最后棧里還有元素&#xff0c…