网络编程异步connect学习
1、概述
下面问题你会怎么回答
异步connect大致流程是什么?
2、回复
1、创建socket
2、设置socket非阻塞
3、调用connect,并处理返回值
4、调用io复用函数,检测socket可写
5、在Linux环境,要调用getsockopt检测socket是否出错,若没有出错,则连接成功
原因:在linux环境即使连接没有成功,socket也有可能是可写的,所以要调用getsockopt检测下
示例代码
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>#define SERVER_IP "192.168.202.224"
#define SERVER_PORT 8082
#define INVALID_HANDLE_VALUE (-1)int main()
{// 创建非阻塞socketint clientfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);if(clientfd == INVALID_HANDLE_VALUE){perror("clientfd creation failed");return -1;}// 发起非阻塞的connect,并处理返回值for(;;){struct sockaddr_in servAddr;servAddr.sin_family = AF_INET;servAddr.sin_addr.s_addr = inet_addr(SERVER_IP);servAddr.sin_port = htons(SERVER_PORT);int ret = connect(clientfd, (struct sockaddr*)&servAddr, sizeof(servAddr));if(ret == 0){printf("connect success\n");return 0;}else if(ret == -1){if(errno == EINTR){// 被系统信号打断printf("connect errno EINTR continue\n");continue;}else if(errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK){break;}else{printf("connect failed errno:%d\n", errno);return -1;}}}// 使用io复用函数,检测socket是否可写fd_set write_fds;FD_ZERO(&write_fds);FD_SET(clientfd, &write_fds);int max_fd = clientfd + 1;struct timeval tv;tv.tv_sec = 3;tv.tv_usec = 0;if(select(max_fd, NULL, &write_fds, NULL, &tv) != 1){printf("select failed errno:%d\n", errno);return -1;}// 检测socket上是否有错误int err;socklen_t len = sizeof(err);if(getsockopt(clientfd, SOL_SOCKET, SO_ERROR, &err, &len) < 0){close(clientfd);return -1;}if(err == 0){printf("connect success\n");}else{ printf("connect failed err:%d\n", err);}close(clientfd);return 0;
}
学习链接:https://github.com/0voice