异步connect

//关于tcp连接的异步connect实现流程如下:
//(1)设置socket连接为非阻塞.
//(2)调用connect函数.返回0表明连接成功.如果返回-1,同时errno为EINPROGRESS表明正在建立连接.
//(3)使用select , epoll等 , 当描述符可写的时候检查连接状态.

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <string.h>

void setnonblock(int fd)
{
    int flags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

int main(){
	const char* ip = "127.0.0.1";
	short port = 9999;
	
	//设置连接地址
	struct sockaddr_in addr;
	socklen_t socklen = sizeof(struct sockaddr_in);
	memset(&addr , 0 , sizeof(struct sockaddr_in));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(ip);
	addr.sin_port = htons(port);
	
	//创建描述符
	int fd = socket( AF_INET , SOCK_STREAM , 0);
	if (fd < 0){
		printf("socket() error\n");
		return -1;
	}
	//设置描述符为非阻塞
	setnonblock(fd);
	
	//连接
	int res;
	res = connect(fd , (struct sockaddr*)&addr , socklen);
	if (res == 0){
		printf("connect ok(1)\n");
	} else if (res == -1 && errno != EINPROGRESS){
		printf("connect err(1)\n");
		close(fd);
		return -1;
	} else {
		int epfd;
		//创建epoll描述符
		epfd = epoll_create(1024);
		if ( (epfd = epoll_create(1024) ) == -1){
			printf("epoll_create() err\n");
			close(fd);
			return -1;
		}
		//添加关注事件
		struct epoll_event ev;
		ev.events = EPOLLOUT;
		ev.data.fd = fd;
		epoll_ctl( epfd , EPOLL_CTL_ADD , fd , &ev);
		
		//编写网络程序的时候,epoll是程序的主循环.我们这里为了测试,连接上或connect超时(75秒)就break掉.
		//正常的流程是写一个处理connect结果的回调函数.
		int event_max = 1;
		struct epoll_event events[event_max];
		int i;
		while (1){
			res = epoll_wait( epfd , events , event_max , -1);
			if (res > 0){
				for ( i = 0 ; i < res ; i++){
					if ( events[i].data.fd == fd && ( events[i].events & EPOLLOUT) ){ //29(EPOLLOUT|EPOLLERR|EPOLLHUP)  //4(EPOLLOUT)
						//检查是否连接成功
						int optval;
						socklen_t optlen = sizeof(optval);
						int res1 = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen);
						if ( res1 < 0 || optval){
							close(fd);
							close(epfd);
							printf("connect err(2)\n");
							return -1;
						} else {
							printf("connect ok(2)\n");
						}
					}
				}
				break;
			}
		}
		close(fd);
		close(epfd);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值