大家来探讨一下socket连接超时的问题

发表于:2007-05-26来源:作者:点击数: 标签:
[size=18:ac54d21053]在客户端与 服务器 端通过socket连接时,有两个问题必须考虑 1、connect连接时可能会发生连接不上的情况,需要实现超时退出程序。 2、连接后在接收数据的过程中,可能发生网络中断,不能接受数据的情况,需要退出程序。 这两个问题应该

[size=18:ac54d21053]在客户端与服务器端通过socket连接时,有两个问题必须考虑
1、connect连接时可能会发生连接不上的情况,需要实现超时退出程序。
2、连接后在接收数据的过程中,可能发生网络中断,不能接受数据的情况,需要退出程序。

这两个问题应该很常见,希望高手给大家详细地讲解一下,谢谢。[/size:ac54d21053]

 gadfly 回复于:2003-08-11 14:40:32
这两个都可以用非阻塞socket,select控制超时

 yuanyawei 回复于:2003-08-12 09:08:00
我觉得第一种情况用select可以很好解决。
但第二种情况在遇到客户端直接拔网线的情况时,server端的情况较难判断,要看内核的参数,linux下较好处理,BSD也没问题,HP和AIX也能处理,但SCO下就不好办了(参数老调不好)。

 minsky 回复于:2003-08-12 10:52:27
1.connect超时:
1)setsockopt();//将socket置为非阻塞模式;
2)connect();
3)判断connect()的返回值,一般情况会返回-1,这时你还必须判断错误码如果是EINPROGRESS,那说明connect还在继续;如果错误码不是前者那么就是有问题了,不必往下执行,必须关掉socket;待下次重联;
4)select();设置好函数中的超时时间,将select()中的read和write项置上,在超时时间内,如果select返回1,即描述字变为了可写,那么连接成功;如果返回2,即描述字变为即可读又可写,那么出错;如果返回0,那么超时;
============================================
2.网络中断:
如果你的程序是客户端.用select检查描述符的状态,如果可读就recv(),根据recv()的返回值来判断网络情况;

 calfen 回复于:2003-12-18 15:18:55
unp上明确说setsockopt只能用在读写时候不能用在connect上啊...

 grouploo 回复于:2004-06-25 23:06:35
/********************************************/
/****   作者::夕君                **/
/****   时间:2004.04.04                     **/
/****   北京金万维科技 http://www.gnway.com           **/
/*******************************************/
/*此函数实现判断m_server的m_port端口是否可以连上,超时限制为nTimeOut秒*/
BOOL ConnectTest(char * m_server,int m_port)
{

        struct hostent* host = NULL;
        struct sockaddr_in saddr;
        unsigned int s = 0;
        BOOL  ret;
        time_t start;
        int error;
        host = gethostbyname (m_server);
        if (host==NULL)return  FALSE;

        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(m_port);
        saddr.sin_addr = *((struct in_addr*)host->h_addr);


        if( (s=socket(AF_INET, SOCK_STREAM, 0))<0){
                return FALSE;
        }


        fcntl(s,F_SETFL, O_NONBLOCK);

        if(connect(s,(struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
                if (errno == EINPROGRESS){// it is in the connect process
                        struct timeval tv;
                        fd_set writefds;
                        tv.tv_sec = m_nTimeOut;
                        tv.tv_usec = 0;
                        FD_ZERO(&writefds);
                        FD_SET(s, &writefds);
                        if(select(s+1,NULL,&writefds,NULL,&tv)>0){
                                int len=sizeof(int);
                               //下面的一句一定要,主要针对防火墙
                                getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len);
                                if(error==0) ret=TRUE;
                                else ret=FALSE;
                        }else   ret=FALSE;//timeout or error happen
                }else ret=FALSE;
        }
        else    ret=TRUE;

        close(s);
        return ret;


}

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)