网站建设优化汕头,火锅自助餐网站建设,wordpress 图集功能,网页模板下载后怎么用在connect连接中#xff0c;若socket以非阻塞的方式进行连接#xff0c;则系统内设置的TCP三次握手超时时间为0#xff0c;所以它不会等待TCP三次握手完成#xff0c;直接返回#xff0c;错误为EINPROGRESS。 所以#xff0c;我们可以通过判断connect时返回的错误码是… 在connect连接中若socket以非阻塞的方式进行连接则系统内设置的TCP三次握手超时时间为0所以它不会等待TCP三次握手完成直接返回错误为EINPROGRESS。 所以我们可以通过判断connect时返回的错误码是不是EINPROGRESS来实现非阻塞的connect如果当前是EINPROGRESS并且socket可写则说明链路建立成功。此时调用getsockopt来清除文件描述符上的错误信息接下来如果没有错误信息则链路成功建立。 B站一位UP主的讲解
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h
#include stdlib.h
#include assert.h
#include stdio.h
#include time.h
#include errno.h
#include fcntl.h
#include sys/ioctl.h
#include unistd.h
#include string.h#define BUFFER_SIZE 1023int setnonblocking(int fd){ //对一个文件描述符设置非阻塞int old_option fcntl(fd, F_GETFL); //old_option表示fd的旧文件属性int new_option old_option | O_NONBLOCK; //在old_option上追加非阻塞属性fcntl(fd, F_SETFL, new_option); //给fd设置新属性return old_option; //返回旧属性
}int unblock_connect(const char* ip, int port, int time){int ret 0;struct sockaddr_in address;bzero(address, sizeof(address));address.sin_family AF_INET;inet_pton(AF_INET, ip, address.sin_addr);//将点分十进制转化为网络字节序address.sin_port htons(port);//将主机字节序转换为网络字节序int sockfd socket(PF_INET, SOCK_STREAM, 0);int fdopt setnonblocking(sockfd);ret connect(sockfd, (struct sockaddr*)address, sizeof(address));if(ret 0){//如果连接成功就将旧状态设置回去回复sockfd属性并立即返回printf(connect with server immediately!\n);fcntl(sockfd, F_SETFL, fdopt);//重置sockfd属性return sockfd;}else if(errno ! EINPROGRESS){ //如果连接没有立即建立那么只有当errno时EINPROGRESS时才表示连接还在进行//否则出错返回printf(unblock connect not support!\n);return -1;}fd_set readfds;fd_set writefds;struct timeval timeout;FD_ZERO(readfds); //将readfds的文件描述符集合清空FD_SET(sockfd, writefds); //将sockfd放入writefds的文件描述符集合中timeout.tv_sec time;timeout.tv_usec 0;ret select(sockfd 1, NULL, writefds, NULL, timeout);//监听所有文件描述符中的可读事件返回就绪文件的文件描述符if(ret 0){/*select 超时或者出错立即返回*/printf(connection time out\n);close(sockfd);return -1;}if(!FD_ISSET(sockfd, writefds)){//检查sockfd是否在writefds的集合中printf(no events on sockfd found\n);close(sockfd);return -1;}int error 0;socklen_t length sizeof(error);/*调用getsockopt来获取并清除sockfd上的错误*/if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, error, length) 0){printf(get socket option failed\n);close(sockfd);return -1;}/*错误号不为0表示连接出错*/if(error ! 0){printf(connection failed after select with the error: %d \n, error);close(sockfd);return -1;}/*连接成功*/printf(connection ready after select with the socket: %d \n, sockfd);fcntl(sockfd, F_SETFL, fdopt);return sockfd;
}int main(int argc, char* argv[]){if(argc 2){printf(usag: %s ip_address port_number\n, basename(argv[0]));return 1;}const char* ip argv[1];int port atoi(argv[2]);int fd unblock_connect(ip, port, 0);if(fd 0 ) return 1;close(fd);return 0;
}