日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

非阻塞connect的实现

發(fā)布時(shí)間:2025/4/5 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 非阻塞connect的实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

步驟1: 設(shè)置非阻塞,啟動(dòng)連接

實(shí)現(xiàn)非阻塞 connect ,首先把 sockfd 設(shè)置成非阻塞的。這樣調(diào)用

connect 可以立刻返回,根據(jù)返回值和 errno 處理三種情況:

(1) 如果返回 0,表示 connect 成功。

(2) 如果返回值小于 0, errno 為 EINPROGRESS, ?表示連接

? ? ? 建立已經(jīng)啟動(dòng)但是尚未完成。這是期望的結(jié)果,不是真正的錯(cuò)誤。

(3) 如果返回值小于0,errno 不是 EINPROGRESS,則連接出錯(cuò)了。

?

步驟2:判斷可讀和可寫

然后把 sockfd 加入 select 的讀寫監(jiān)聽集合,通過 select 判斷 sockfd

是否可寫,處理三種情況:

(1) 如果連接建立好了,對(duì)方?jīng)]有數(shù)據(jù)到達(dá),那么 sockfd 是可寫的

(2) 如果在 select 之前,連接就建立好了,而且對(duì)方的數(shù)據(jù)已到達(dá),

? ? ? 那么 sockfd 是可讀和可寫的。

(3) 如果連接發(fā)生錯(cuò)誤,sockfd 也是可讀和可寫的。

判斷 connect 是否成功,就得區(qū)別 (2) 和 (3),這兩種情況下 sockfd 都是

可讀和可寫的,區(qū)分的方法是,調(diào)用 getsockopt?檢查是否出錯(cuò)。

?

步驟3:使用 getsockopt 函數(shù)檢查錯(cuò)誤

getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len)

在 sockfd 都是可讀和可寫的情況下,我們使用 getsockopt 來檢查連接

是否出錯(cuò)。但這里有一個(gè)可移植性的問題。

如果發(fā)生錯(cuò)誤,getsockopt 源自 Berkeley 的實(shí)現(xiàn)將在變量 error 中

返回錯(cuò)誤,getsockopt 本身返回0;然而 Solaris 卻讓 getsockopt 返回 -1,

并把錯(cuò)誤保存在 errno 變量中。所以在判斷是否有錯(cuò)誤的時(shí)候,要處理

這兩種情況。

?

代碼:

?

int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec) {int flags, n, error, code;socklen_t len;fd_set wset;struct timeval tval;flags = fcntl(sockfd, F_GETFL, 0);fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);error = 0;if ((n = connect(sockfd, saptr, salen)) == 0) {goto done;} else if (n < 0 && errno != EINPROGRESS){return (-1);}/* Do whatever we want while the connect is taking place */FD_ZERO(&wset);FD_SET(sockfd, &wset);tval.tv_sec = nsec;tval.tv_usec = 0;if ((n = select(sockfd+1, NULL, &wset, NULL, nsec ? &tval : NULL)) == 0) {close(sockfd); /* timeout */errno = ETIMEDOUT;return (-1);}if (FD_ISSET(sockfd, &wset)) {len = sizeof(error);code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);/* 如果發(fā)生錯(cuò)誤,Solaris實(shí)現(xiàn)的getsockopt返回-1,* 把pending error設(shè)置給errno. Berkeley實(shí)現(xiàn)的* getsockopt返回0, pending error返回給error. * 我們需要處理這兩種情況 */if (code < 0 || error) {close(sockfd);if (error) errno = error;return (-1);}} else {fprintf(stderr, "select error: sockfd not set");exit(0);}done:fcntl(sockfd, F_SETFL, flags); /* restore file status flags */return (0); }

總結(jié)

以上是生活随笔為你收集整理的非阻塞connect的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。