Socket connect() 设置超时时间

Socket connect() 设置超时时间

1,linux或者win32控制台程序中connect函数默认是阻塞的,成功则返回0,失败返回-1,错误码可以用函数GetLastError获得。如果连接一个打开的服务器一般回立即返回并且成功连接socket连接,如果连接一个存在但是没有开启的服务器会阻塞一段时间(不会太长)然后返回-1. 还有一种就是连接一个网内不存在的服务器,比如192.168.0.256。这时就会阻塞很长的时间大概20+秒。这篇文章最初就是为了解决这个问题而写的。
2,为了处理connect的连接超时可以在调用socket函数之后使用fcntl函数将sock描述符设置为非阻塞,然后进行连接(connect),会立即返回-1,判断错误码是否等于EINPROGRESS,也就是判断连接是不是正在进行中,如果是那么通过select查询在一段时间内该描述符是否可写来判断连接是成功还是失败。如果错误码不等于EINPROGRESS那么连接失败。下面给出linux和window具体实现方法.

WINDOWS:

int main()
{
 SOCKET sock;
 SOCKADDR_IN addr;
 fd_set r;
 unsigned long ul = 1;

 struct timeval timeo = {3, 0};
 //创建socket描述符
 if((sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
 {
  printf("socket fail");
  return -1;
 }
    //设置阻塞
 if(ioctlsocket(sock, FIONBIO, (unsigned long*)&ul) == SOCKET_ERROR)
 {
  printf("ioctlsocket fail");
  return -1;
 }
 //初始化addr。。。。。。



 //发起连接
 if(connect(sock, (const struct sockaddr*)addr, sizeof(addr)) == SOCKET_ERROR)
 {
  FD_ZERO(&r);
  FD_SET(scok, &r);
  if(select(0, &r, 0, 0, &timeo) <= 0)) //需要注意select函数第一个参数在winsock被忽略了,

                                        //在linux必须是sock+1;
  {
   printf("connect fail");
   return -1;
  }
  else
  {
   printf("connect success");
   //to do
  }
 }
}

#include<stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>

int main(int argc,char*argv[])
{
        int fd, retval;
        structsockaddr_in addr;
        structtimeval timeo={3, 0};  //初始化超时时间
        socklen_t len=sizeof(timeo);
        fd_set set;

        fd =socket(AF_INET,SOCK_STREAM, 0);
        if(argc== 4)
                timeo.tv_sec=atoi(argv[3]);
        fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)| O_NONBLOCK); //将fd设置为非阻塞
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr= inet_addr(argv[1]);
        addr.sin_port=htons(atoi(argv[2]));
        printf("%dn",time(NULL));
        if(connect(fd,(structsockaddr*)&addr,sizeof(addr))== 0){
                printf("connectedn");       
                return 0;
        }
        if(errno!= EINPROGRESS){
                perror("connect");
                return-1;
        }
        FD_ZERO(&set);
        FD_SET(fd,&set);
        retval = select(fd+ 1,NULL, &set,NULL,&timeo);
        if(retval==-1){
                perror("select");
                return-1;
        }elseif(retval== 0){
                fprintf(stderr,"timeoutn");
                printf("%dn",time(NULL));
                return 0;
        }
        printf("connectedn");

        return 0;
}

如果连接成功后需要将该连接设成阻塞的那么再次调用fcntl函数

fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) ^ O_NONBLOCK);  
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值