//关于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);
}
}
异步connect
最新推荐文章于 2023-12-21 14:51:05 发布