日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

如何設(shè)置socket的Connect超時

系統(tǒng) 2113 0
1.首先將標志位設(shè)為Non-blocking模式,準備在非阻塞模式下調(diào)用connect函數(shù)
2.調(diào)用connect,正常情況下,因為TCP三次握手需要一些時間;而非阻塞調(diào)用只要不能立即完成就會返回錯誤,所以這里會返回EINPROGRESS,表示在建立連接但還沒有完成。
3.在讀套接口描述符集(fd_set rset)和寫套接口描述符集(fd_set
wset)中將當前套接口置位(用FD_ZERO()、FD_SET()宏),并設(shè)置好超時時間(struct
timeval *timeout)
4.調(diào)用select( socket, &rset, &wset, NULL, timeout )
返回0表示connect超時
如果你設(shè)置的超時時間大于75秒就沒有必要這樣做了,因為內(nèi)核中對connect有超時限制就是75秒。

網(wǎng)絡(luò)編程中socket的分量我想大家都很清楚了,socket也就是套接口,在套接口編程中,提到超時的概念,我們一下子就能想到3個:發(fā)送超時,接收超時,以及select超時(注:
select函數(shù)并不是只用于套接口的,但是套接口編程中用的比較多),在connect到目標主機的時候,這個超時是不由我們來設(shè)置的。不過正常情況下這個超時都很長,并且connect又是一個阻塞方法,一個主機不能連接,等著connect返回還能忍受,你的程序要是要試圖連接多個主機,恐怕遇到多個不能連接的主機的時候,會塞得你受不了的。我也廢話少說,先說說我的方法,如果你覺得你已掌握這種方法,你就不用再看下去了,如果你還不了解,我愿意與你分享。本文是已在Linux下的程序為例子,不過拿到Windows中方法也是一樣,無非是換幾個函數(shù)名字罷了。
Linux中要給connect設(shè)置超時,應(yīng)該是有兩種方法的。一種是該系統(tǒng)的一些參數(shù),這個方法我不講,因為我講不清楚:P,它也不是編程實現(xiàn)的。另外一種方法就是變相的實現(xiàn)connect的超時,我要講的就是這個方法,原理上是這樣的:
1.建立socket
2.將該socket設(shè)置為非阻塞模式
3.調(diào)用connect()
4.使用select()檢查該socket描述符是否可寫(注意,是可寫)
5.根據(jù)select()返回的結(jié)果判斷connect()結(jié)果
6.將socket設(shè)置為阻塞模式(如果你的程序不需要用阻塞模式的,這步就省了,不過一般情況下都是用阻塞模式的,這樣也容易管理)
如果你對網(wǎng)絡(luò)編程很熟悉的話,其實我一說出這個過程你就知道怎么寫你的程序了,下面給出我寫的一段程序,僅供參考。
/******************************
* Time out for connect()
* Write by Kerl W
******************************/
#include <sys/socket.h>
#include <sys/types.h>
#define TIME_OUT_TIME 20 //connect超時時間20秒
int main(int argc , char **argv)
{
………………
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) exit(1);
struct sockaddr_in serv_addr;
………//以服務(wù)器地址填充結(jié)構(gòu)serv_addr
int error=-1, len;
len = sizeof(int);
timeval tm;
fd_set set;
unsigned long ul = 1;
ioctl(sockfd, FIONBIO, &ul); //設(shè)置為非阻塞模式
bool ret = false;
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) ==
-1)
{
tm.tv_set = TIME_OUT_TIME;
tm.tv_uset = 0;
FD_ZERO(&set);
FD_SET(sockfd, &set);
if( select(sockfd+1, NULL, &set, NULL, &tm) > 0)
{
getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error == 0) ret = true;
else ret = false;
} else ret = false;
}
else ret = true;
ul = 0;
ioctl(sockfd, FIONBIO, &ul); //設(shè)置為阻塞模式
if(!ret)
{
close( sockfd );
fprintf(stderr , "Cannot Connect the server!n");
return;
}
fprintf( stderr , "Connected!n");
//下面還可以進行發(fā)包收包操作
……………
}

以上代碼片段,僅供參考,也是為初學(xué)者提供一些提示,主要用到的幾個函數(shù),select,
ioctl,
getsockopt都可以找到相關(guān)資料,具體用法我這里就不贅述了,你只需要在linux中輕輕的敲一個man
<函數(shù)名>就能夠看到它的用法。
此外我需要說明的幾點是,雖然我們用ioctl把套接口設(shè)置為非阻塞模式,不過select本身是阻塞的,阻塞的時間就是其超時的時間由調(diào)用select
的時候的最后一個參數(shù)timeval類型的變量指針指向的timeval結(jié)構(gòu)變量來決定的,timeval結(jié)構(gòu)由一個表示秒數(shù)的和一個表示微秒數(shù)(long類型)的成員組成,一般我們設(shè)置了秒數(shù)就行了,把微妙數(shù)設(shè)為0(注:1秒等于100萬微秒)。而select函數(shù)另一個值得一提的參數(shù)就是上面我們用到的fd_set類型的變量指針。調(diào)用之前,這個變量里面存了要用select來檢查的描述符,調(diào)用之后,針對上面的程序這里面是可寫的描述符,我們可以用宏FD_ISSET來檢查某個描述符是否在其中。由于我這里只有一個套接口描述符,我就沒有使用FD_ISSET宏來檢查調(diào)用select之后這個sockfd是否在set里面,其實是需要加上這個判斷的。不過我用了getsockopt來檢查,這樣才可以判斷出這個套接口是否是真的連接上了,因為我們只是變相的用select來檢查它是否連接上了,實際上select檢查的是它是否可寫,而對于可寫,是針對以下三種條件任一條件滿足時都表示可寫的:
1)套接口發(fā)送緩沖區(qū)中的可用控件字節(jié)數(shù)大于等于套接口發(fā)送緩沖區(qū)低潮限度的當前值,且或者i)套接口已連接,或者ii)套接口不要求連接(UDP方式的)
2)連接的寫這一半關(guān)閉。
3)有一個套接口錯誤待處理。
這樣,我們就需要用getsockopt函數(shù)來獲取套接口目前的一些信息來判斷是否真的是連接上了,沒有連接上的時候還能給出發(fā)生了什么錯誤,當然我程序中并沒有標出那么多狀態(tài),只是簡單的表示可連接/不可連接。
下面我來談?wù)剬@個程序測試的結(jié)果。我針對3種情形做了測試:
1. 目標機器網(wǎng)絡(luò)正常的情況
可以連接到目標主機,并能成功以阻塞方式進行發(fā)包收包作業(yè)。
2. 目標機器網(wǎng)絡(luò)斷開的情況
在等待設(shè)置的超時時間(上面的程序中為20秒)后,顯示目標主機不能連接。
3. 程序運行前斷開目標機器網(wǎng)絡(luò),超時時間內(nèi),恢復(fù)目標機器的網(wǎng)絡(luò)
在恢復(fù)目標主機網(wǎng)絡(luò)連接之前,程序一只等待,恢復(fù)目標主機后,程序顯示連接目標主機成功,并能成功以阻塞方式進行發(fā)包收包作業(yè)。
以上各種情況的測試結(jié)果表明,這種設(shè)置connect超時的方法是完全可行的。我自己是把這種設(shè)置了超時的connect封裝到了自己的類庫,用在一套監(jiān)控系統(tǒng)中,到目前為止,運行還算正常。這種編程實現(xiàn)的connect超時比起修改系統(tǒng)參數(shù)的那種方法的有點就在于它只用于你的程序之中而不影響系統(tǒng)。

如何設(shè)置socket的Connect超時


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 阿坝| 铅山县| 灵寿县| 宝坻区| 哈巴河县| 昌吉市| 鸡西市| 杭州市| 安徽省| 昌平区| 阿图什市| 青铜峡市| 雅安市| 运城市| 云龙县| 宁化县| 武强县| 石渠县| 招远市| 沙湾县| 通许县| 六盘水市| 新巴尔虎左旗| 富顺县| 巴楚县| 涿州市| 太仓市| 遂昌县| 法库县| 虎林市| 巴林右旗| 乌拉特后旗| 临澧县| 兴山县| 射洪县| 雷山县| 淮滨县| 潜江市| 凌海市| 内江市| 大庆市|