• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 創建能夠超時的socket連結API

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    在socket編程中調用connect函數連接一遠程機器,如果該ip不存在的話,connect將在一段時間內返回-1表示失敗。問題是有時候我們需要準確控制connect函數連接的時間,這就需要我們能夠控制這個connect函數。但是,gcc給我們提供的API沒有這個功能。我自己設計了
    在socket編程中調用connect函數連接一遠程機器,如果該ip不存在的話,connect將在一段時間內返回-1表示失敗。問題是有時候我們需要準確控制connect函數連接的時間,這就需要我們能夠控制這個connect函數。但是,gclearcase/" target="_blank" >cc給我們提供的API沒有這個功能。我自己設計了一個這樣的API函數--connect2,它能夠在用戶設置的一段時間后,連接超時退出。

          這個connect2的初步設計思想是利用多線程,創建一個獨立的線程調用socket的connect函數去連接,這樣這個線程就可以被殺掉。我們首先要根據用戶的需求設立一個alarm,并設置好alarm到點之后的動作,那就是取消掉連接線程。如果在alarm到點之前這個線程已經返回那就返回連接成功,否則連接線程將被取消,也就說明連接在規定的時間內失敗,函數返回失敗。

          好了。設計思想比較簡單。下面來看看實現。
    //函數定義

    int connect2(SOCKET sock,struct sockaddr * addr,int timeout)

    //函數實現

    /**This implementation is for LINUX
    * @version 1.0
    * @author Jerry Hou
    */
    #include
    #include
    #include
    #include
    #include
    #include
    #include "connect_timeout.h"
    int g_sock;
    pthread_t connect_thread;
    void *sock_connect(void * argv);
    void sock_cancel(int no);
    int connect2(SOCKET sock,struct sockaddr * addr,int timeout)
    {
            int res;
            struct sigaction act;
            g_sock=sock;
            res=pthread_create(&connect_thread,NULL,sock_connect,(void *)addr);
            if(res!=0)
                    return errno;
            act.sa_handler=sock_cancel;
            sigemptyset(&act.sa_mask);
            act.sa_flags=0;
            if(sigaction(SIGALRM,&act,NULL)<0)
            {
                    return errno;
            }

            alarm(timeout);
            int * pres=NULL;
            res=pthread_join(connect_thread,(void **)&pres);
            alarm(0);
            if(res!=0)
                    return errno;
            if(pres!=NULL)
            if(pres==PTHREAD_CANCELED)
                    return -1;
            return *pres;
      

    }
    void * sock_connect(void * argv)
    {
            struct sockaddr * s_addr=(struct sockaddr *)argv;
            int *pres=(int *)malloc(sizeof(int));
            int res=connect(g_sock,s_addr,sizeof(struct sockaddr_in));
            *pres=res;
            pthread_exit(pres);
    }
    void sock_cancel(int no)
    {
            pthread_cancel(connect_thread);
    //      timeout=1;
    }

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    這個connect2 API能夠較準確在規定時間內TIMEOUT,但是還有一些問題。先不說了,改天有空再說。希望有人捧場。

         接著上面的討論。細心的朋友會發現這個connect2函數的問題,那就是它只能允許在一個connect2調用完才能進行第二個調用,否則另外一個調用會影響到前面的調用。也就是說,只能在單線程中使用,不是線程安全(thread-safe)或可重入的(reentrant)。
         造成這個原因一是設計中我們調用了alarm這個gcc庫的api,而它是進程范圍的,也就是說后邊alarm設置會影響到前面的設置。二是我們使用了2個全局變量,這樣后邊的connect2調用會改寫這2個變量影響到前面的調用。
         解決的辦法是我們需要一個線程安全的定時器timer,無論哪個定時器的設置都不會影響到其他的定時器工作。理想的這樣一個timer函數應該是這樣定義的:
    int timer(int seconds,(void)ontimer(void * agrv) ,void *argv); 其中,seconds是超時時間,timerfunc是超時要執行的函數地址,argv是傳入該函數的參數。好,我們假設有了這樣一個線程安全的timer,我們來重寫connect2。timer的實現我放在另外一篇文章里單獨介紹,因為它不僅可以用在這里。

    /**This implementation is for LINUX
    * @version 1.1
    * @author Jerry Hou
    */
    #include
    #include
    #include
    #include
    #include
    #include "timer.h"  //header file containing definitions of timer related APIs
    #include "connect_timeout.h"

    void * sock_connect(void * argv);
    void  sock_cancel(void * argv);
    int connect2(SOCKET sock,struct sockaddr * addr,int timeout)
    {
            int res;
            pthread_t connect_thread;
            res=pthread_create(&connect_thread,NULL,sock_connect,(void *)addr);
            if(res!=0)
                    return errno;
            res=timer(timeout,socke_cancel,(void *)&connect_thread);
            if(res!=0)
                    return res;
            int * pres=NULL;
            res=pthread_join(connect_thread,(void **)&pres);
            if(res!=0)
                    return errno;
            if(pres!=NULL)
            if(pres==PTHREAD_CANCELED)
                    return -1;
            return *pres;
      

    }
    void * sock_connect(void * argv)
    {
            struct sockaddr * s_addr=(struct sockaddr *)argv;
            int *pres=(int *)malloc(sizeof(int));
            int res=connect(g_sock,s_addr,sizeof(struct sockaddr_in));
            *pres=res;
            pthread_exit(pres);
    }
    void  sock_cancel(void * argv)
    {
            pthead_t *pthread=(pthead_t *)argv;
            pthread_cancel(pthread);
    //      timeout=1;
    }

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>