非阻塞情況下connect產(chǎn)生EINPROGRESS錯(cuò)誤

小云
108
2023-09-28 09:51:05
欄目: 編程語言

在非阻塞情況下,當(dāng)調(diào)用connect函數(shù)時(shí),如果連接無法立即建立,connect函數(shù)會(huì)立即返回,并且返回錯(cuò)誤碼EINPROGRESS。這表示連接正在進(jìn)行中。

在非阻塞模式下,connect函數(shù)的返回值并不表示連接是否成功建立,而是表示連接操作是否已經(jīng)開始。如果連接成功建立,可以使用select、poll或epoll等I/O多路復(fù)用函數(shù)來檢測(cè)套接字是否可寫,以確定連接是否已完成。

在連接完成之前,可以使用getsockopt函數(shù)來獲取套接字的SO_ERROR選項(xiàng)值,如果該值為0,則表示連接成功建立;如果該值為其他錯(cuò)誤碼,則表示連接失敗??梢允褂梅亲枞姆绞絹頇z查連接的完成狀態(tài),以便繼續(xù)執(zhí)行其他操作。

以下是一個(gè)使用非阻塞connect的示例代碼:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
int main() {
int sockfd;
struct sockaddr_in server_addr;
int ret;
// 創(chuàng)建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(1);
}
// 設(shè)置套接字為非阻塞
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
perror("fcntl");
exit(1);
}
// 初始化服務(wù)器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 發(fā)起連接請(qǐng)求
ret = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ret == -1 && errno != EINPROGRESS) {
perror("connect");
exit(1);
}
// 使用select函數(shù)等待套接字可寫
fd_set write_fds;
FD_ZERO(&write_fds);
FD_SET(sockfd, &write_fds);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
ret = select(sockfd + 1, NULL, &write_fds, NULL, &timeout);
if (ret == -1) {
perror("select");
exit(1);
} else if (ret == 0) {
printf("connect timeout\n");
exit(1);
}
// 檢查套接字的錯(cuò)誤狀態(tài)
int error = 0;
socklen_t len = sizeof(error);
ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
if (ret == -1) {
perror("getsockopt");
exit(1);
}
if (error != 0) {
printf("connect failed: %s\n", strerror(error));
exit(1);
}
printf("connect successful\n");
close(sockfd);
return 0;
}

在該示例代碼中,首先創(chuàng)建一個(gè)套接字,并將其設(shè)置為非阻塞模式。然后,使用connect函數(shù)發(fā)起連接請(qǐng)求。如果connect返回-1并且errno不等于EINPROGRESS,表示連接失敗,程序會(huì)打印錯(cuò)誤信息并退出。

如果連接請(qǐng)求正在進(jìn)行中,程序會(huì)使用select函數(shù)等待套接字可寫。如果select返回-1,表示發(fā)生錯(cuò)誤,程序會(huì)打印錯(cuò)誤信息并退出。如果select返回0,表示連接超時(shí),程序會(huì)打印相應(yīng)的提示信息并退出。

在連接請(qǐng)求完成后,程序會(huì)使用getsockopt函數(shù)來獲取套接字的錯(cuò)誤狀態(tài)。如果錯(cuò)誤狀態(tài)為0,表示連接成功建立。如果錯(cuò)誤狀態(tài)為其他值,表示連接失敗,程序會(huì)打印相應(yīng)的錯(cuò)誤信息并退出。

以上是一個(gè)使用非阻塞connect的示例代碼,可以根據(jù)實(shí)際情況進(jìn)行修改和擴(kuò)展。

0