• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: 小 中 大 | 推荐给好友 上一篇 | 下一篇

创建能够超时的socket连结API

发布: 2007-7-04 12:06 | 作者: admin | 来源:  网友评论 | 查看: 19次 | 进入软件测试论坛讨论

领测软件测试网 在socket编程中调用connect函数连接一远程机器,如果该ip不存在的话,connect将在一段时间内返回-1表示失败。问题是有时候我们需要准确控制connect函数连接的时间,这就需要我们能够控制这个connect函数。但是,gcc给我们提供的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;
}

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:[email protected] 电话:010-51297073

软件测试 | 领测国际 | ISTQB | ISTQB官网 | TMMi | TMMi认证 | 国际软件测试工程师认证 | 领测软件测试网