I/O复用的高级应用:非阻塞connect

源码如下:

/********************* Creation Date:2018-05-13  10:38*******************/
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<time.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include<unistd.h>
#include<string.h>

#define BUFFER_SIZE 1023

int setnonblocking (int fd)
{
    int old_option = fcntl(fd , F_GETFL);
    int new_option = old_option |O_NONBLOCK;
    fcntl(fd,F_SETFL,new_option);
    return old_option;
}

int unblock_connect(const char*ip , int port ,int time)
{
    int ret = 0;
    struct sockaddr_in address;
    bzero(&address,sizeof(address));
    inet_pton(AF_INET ,ip,&address.sin_addr);
    address.sin_port = htons(port);

    int sockfd = socket(PF_INET , SOCK_STREAM,0);
    int fdopt = setnonblocking(sockfd);
    ret = connect(sockfd,(struct sockaddr*)&address,sizeof(address));
    if(ret == 0)
    {
        printf("connect with server immediately.\n");
        fcntl(sockfd, F_SETFL,fdopt);
        return sockfd;
    }
    else if(errno != EINPROGRESS  ) 
    {
        printf("unblock connect not support\n");
        return -1;
    }

    fd_set readfds;
    fd_set writefds;
    struct timeval timeout;

    FD_ZERO(&readfds);
    FD_SET(sockfd,&writefds);
    timeout.tv_sec = time;
    timeout.tv_usec = 0;
    ret = select(sockfd +1 ,NULL,&writefds , NULL,&timeout);
    if(ret <= 0)
    {
        printf("connect time out\n");
        close(sockfd);
        return -1;
    }

    if(! FD_ISSET(sockfd,&writefds))
    {
        printf("no events on sockfd found\n");
        close(sockfd);
        return -1;
    }

    int error = 0;
    socklen_t length = sizeof(error);

    if(getsockopt(sockfd , SOL_SOCKET ,SO_ERROR,&error,&length) < 0)
    {
        printf("get socket option failed\n");
        close(sockfd);
        return -1;
    }
    if(error != 0)
    {
        printf("connect failed after select whih the error: %d\n",error);
        close(sockfd);
        return -1;
    }
    printf("connection ready after select with the socket:%d\n",sockfd);
    fcntl(sockfd,F_SETFL , fdopt);
    return sockfd;
}

int main(int argc , char *argv[])
{
    if(argc <= 2)
        {
            printf("usage: %s ip_address port_num\n",basename(argv[0]));

        }
    const char* ip = argv[1];
    int port = atoi(argv[2]);

    int sockfd = unblock_connect(ip , port ,10);
    if(sockfd < 0)
    {
        return 1;
    }
    close(sockfd);
    return 0;
}


参考文献:《Linux高性能服务器编程》

猜你喜欢

转载自blog.csdn.net/zzb2019/article/details/80335367