代码拉取完成,页面将自动刷新
当你调用connect
函数对远程服务器进行连接时,如果使用的是阻塞式套接字,connect
会一直阻塞到连接成功或者发生错误为止。这可能导致应用程序的其它部分无法执行,尤其是在图形用户界面或需要同时处理多个连接的服务器应用程序中,这可能是不可接受的。为了解决connect
函数的阻塞问题,可以采用以下几种方法:
connect
调用将立即返回。如果连接未立即建立,connect
会返回一个错误码,通常是EINPROGRESS
,表明连接尝试正在进行中。select
,poll
或epoll
等函数来监视套接字的状态。当套接字可写时(select
等的写集合中返回),这通常意味着连接已经建立或者连接尝试失败,此时可以使用getsockopt
来检查套接字的SO_ERROR
选项,以确定是否连接成功。libaio
或Windows的IOCP
)或者事件驱动的网络库(比如libevent
、libuv
或Boost.Asio
),可以在不阻塞主线程的情况下执行connect
。connect
调用,这样即使connect
阻塞,也不会影响主线程或进程的执行。O_NONBLOCK
与connect
结合后的特殊处理:
connect
可能立即返回-1
,并设置errno
为EINPROGRESS
。在这种情况下,可以使用select
或poll
等函数来监视连接是否成功。下面用代码来举一个例子:我们先将套接字设置为非阻塞,然后尝试连接。如果connect
返回EINPROGRESS
错误,我们利用select
监视套接字的写事件,如果select
返回后,套接字的写事件被触发,则调用getsockopt
检查SO_ERROR
,看是否连接成功。
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
// ...
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// 设置套接字为非阻塞
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
struct sockaddr_in server_addr;
// 设置server_addr的成员变量...
// ...
int result = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (result < 0) {
if (errno == EINPROGRESS) {
// 连接正在尝试中
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(sockfd, &writefds);
struct timeval timeout = {5, 0}; // 设置超时时间
// 使用select等待连接完成或超时
result = select(sockfd + 1, NULL, &writefds, NULL, &timeout);
if (result <= 0) {
// select错误或超时
perror("select");
close(sockfd);
return -1;
} else {
int error = 0;
socklen_t len = sizeof(error);
// 获取套接字选项
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
perror("getsockopt");
close(sockfd);
return -1;
}
// 检查是否有错误发生
if (error) {
errno = error;
perror("connect");
close(sockfd);
return -1;
}
}
} else {
// 连接尝试出错
perror("connect");
close(sockfd);
return -1;
}
}
// 套接字现在已连接
// ...
close(sockfd);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。