非阻塞socket下客户端connect + select简单demo

一个简单实现非阻塞socket,超时响应并判断是否连接成功demo:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>

#define IPADDR "www.baidu.com"
#define PORT 80

int main()
{
  struct addrinfo *res, hint;
    fd_set rest, west;
  int error;
  socklen_t optlen = sizeof(error);
    memset(&hint, 0, sizeof(hint));
    hint.ai_family = AF_INET;
    hint.ai_socktype = SOCK_STREAM;
    if (0 != getaddrinfo(IPADDR, NULL, &hint, &res)) {
        goto err0;
    }

    int sock = socket(res->ai_family, res->ai_socktype, 0);
    if (-1 == sock)
        goto err1;
    if(-1 == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK))
        goto err2;

    struct sockaddr_in addr;

    memset(&addr, 0 , sizeof(addr));
  addr.sin_family = res->ai_family;
  addr.sin_port = htons(PORT);
  addr.sin_addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;

  int ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    printf("ret = %d,errno = %d\n",ret,errno);
  if (-1 == ret && EINPROGRESS != errno)
      goto err2;
  /*添加select超时响应*/
  FD_ZERO(&rest);
  FD_ZERO(&west);
  FD_SET(sock, &rest);
  FD_SET(sock, &west);
    struct timeval tempval;
  tempval.tv_sec = 3;
  tempval.tv_usec = 0;
  int flag = select(sock+1, &rest, &west, NULL, &tempval);//监听套接的可读和可写条件
  if(flag < 0)
    {
      printf("select error\n");
          goto err2;
  }
    else
    {
    /*说明*/
    /*在何时确认连接成功,第一种:可写不可读,第二种:可读可写,通过getsockopt获取
    sock信息,返回值为0且返回错误值也为0的情况连接成功。
    */
        if(!FD_ISSET(sock, &rest) && !FD_ISSET(sock, &west))
        {
            printf("connect no response\n");
            goto err2;
        }
    else if(FD_ISSET(sock, &rest) && FD_ISSET(sock, &west))
    {
      flag = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &optlen);
      if(flag == 0 && error == 0)
      {
        printf("connect success....\n");
      }
      else
      {
        printf("connect error....\n");
        goto err2;
      }
    }
    else if(!FD_ISSET(sock, &rest) && FD_ISSET(sock, &west))
    {
      printf("connect success....\n");
    }
    else
    {
      printf("connect error....\n");
      goto err2;
    }
    }
  close(sock);
  freeaddrinfo(res);
  return 0;
err2:
    close(sock);
err1:
    freeaddrinfo(res);
err0:
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值