​Linux非阻塞connect错误码EINPROGRESS怎么解决

阿里云服务器

在Linux系统中,当使用非阻塞的connect函数尝试建立网络连接时,如果连接不能立即完成(例如,因为需要等待网络响应),connect函数会返回-1并设置错误码EINPROGRESS。这表示连接操作正在进行中,但尚未完成。

处理EINPROGRESS错误码的一般步骤包括:

设置套接字为非阻塞模式:
在调用connect之前,确保套接字已被设置为非阻塞模式。这通常通过fcntl函数或使用O_NONBLOCK标志在socket调用时完成。

使用select、poll或epoll等待连接完成:
一旦connect返回-1并设置EINPROGRESS,你需要使用select、poll或epoll等系统调用来等待套接字变得可写(对于connect来说,这意味着连接已建立或出错)。

检查套接字的状态:
当select、poll或epoll指示套接字可写时,你需要再次检查套接字的错误状态。这通常通过调用getsockopt函数并查询SO_ERROR选项来完成。如果getsockopt返回0,则表示连接成功;如果返回其他错误码,则表示连接失败,并且该错误码指示了失败的原因。

处理连接结果:
根据getsockopt返回的结果,你可以决定是继续处理成功的连接,还是关闭套接字并处理连接失败的情况。

下面是一个使用select来处理非阻塞connect的示例代码片段:

c复制代码

#include <sys/types.h>      

#include <sys/socket.h>      

#include <netinet/in.h>      

#include <arpa/inet.h>      

#include <fcntl.h>      

#include <unistd.h>      

#include <errno.h>      

#include <string.h>      

#include <stdio.h>      


int main() {    

int sockfd;    

struct sockaddr_in server_addr;      

fd_set write_fds;    

struct timeval timeout;      

int result;    

socklen_t len = sizeof(int);    

int err;    


// 创建套接字      

sockfd = socket(AF_INET, SOCK_STREAM, 0);    

if (sockfd < 0) {    

perror("socket");    

return 1;    

}    


// 设置套接字为非阻塞模式      

fcntl(sockfd, F_SETFL, O_NONBLOCK);    


// 设置服务器地址      

memset(&server_addr, 0, sizeof(server_addr));    

server_addr.sin_family = AF_INET;    

server_addr.sin_port = htons(80);    

inet_pton(AF_INET, "93.184.216.34", &server_addr.sin_addr); // 示例IP地址      


// 发起非阻塞连接      

if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {    

if (errno != EINPROGRESS) {    

perror("connect");    

close(sockfd);    

return 1;    

}    

}    


// 设置select超时时间      

timeout.tv_sec = 5; // 5秒超时      

timeout.tv_usec = 0;    


// 等待连接完成      

FD_ZERO(&write_fds);    

FD_SET(sockfd, &write_fds);    

result = select(sockfd + 1, NULL, &write_fds, NULL, &timeout);    

if (result < 0) {    

perror("select");    

close(sockfd);    

return 1;    

} else if (result == 0) {    

fprintf(stderr, "Connect timed out\n");    

close(sockfd);    

return 1;    

}    


// 检查连接结果      

if (FD_ISSET(sockfd, &write_fds)) {    

getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&err, &len);    

if (err == 0) {    

printf("Connected successfully\n");    

// 继续处理连接...      

} else {    

errno = err;    

perror("connect");    

close(sockfd);    

return 1;    

}    

}    


// 关闭套接字(在实际应用中,你可能不会在这里关闭它)      

close(sockfd);    

return 0;    

}    

在这个示例中,我们创建了一个非阻塞的套接字,并尝试连接到指定的服务器。如果connect返回-1并设置EINPROGRESS,我们使用select等待套接字变得可写。然后,我们使用getsockopt检查连接的结果,并根据结果决定是继续处理连接还是关闭套接字。