问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

设置非阻塞 要在connect之前吗

发布网友 发布时间:2024-02-18 16:57

我来回答

1个回答

热心网友 时间:2024-03-18 07:10

1_set = TIME_OUT_TIME;tm.tv_uset = 0;FD_ZERO(&set);FD_SET(sockfd, &set);if( select(sockfd+1, NULL, &set, NULL, &tm) > 0){getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);if(error == 0) ret = true;else ret = false;} else ret = false;}else ret = true;ul = 0;ioctl(sockfd, FIONBIO, &ul); //设置为阻塞模式if(!ret){close( sockfd );fprintf(stderr , "Cannot Connect the server!n");return;}fprintf( stderr , "Connected!n");//下面还可以进行发包收包操作……………}以上代码片段,仅供参考,也是为初学者提供一些提示,主要用到的几个函数,select, ioctl, getsockopt都可以找到相关资料,具体用法我这里就不赘述了,你只需要在linux中轻轻的敲一个man <函数名>就能够看到它的用法。此外我需要说明的几点是,虽然我们用ioctl把套接口设置为非阻塞模式,不过select本身是阻塞的,阻塞的时间就是其超时的时间由调用select 的 时候的最后一个参数timeval类型的变量指针指向的timeval结构变量来决定的,timeval结构由一个表示秒数的和一个表示微秒数(long 类型)的成员组成,一般我们设置了秒数就行了,把微妙数设为0(注:1秒等于100万微秒)。而select函数另一个值得一提的参数就是上面我们用到的 fd_set类型的变量指针。调用之前,这个变量里面存了要用select来检查的描述符,调用之后,针对上面的程序这里面是可写的描述符,我们可以用宏 FD_ISSET来检查某个描述符是否在其中。由于我这里只有一个套接口描述符,我就没有使用FD_ISSET宏来检查调用select之后这个 sockfd是否在set里面,其实是需要加上这个判断的。不过我用了getsockopt来检查,这样才可以判断出这个套接口是否是真的连接上了,因为 我们只是变相的用select来检查它是否连接上了,实际上select检查的是它是否可写,而对于可写,是针对以下三种条件任一条件满足时都表示可写 的:1)套接口发送缓冲区中的可用控件字节数大于等于套接口发送缓冲区低潮限度的当前值,且或者i)套接口已连接,或者ii)套接口不要求连接(UDP方式的)2)连接的写这一半关闭。3)有一个套接口错误待处理。这样,我们就需要用getsockopt函数来获取套接口目前的一些信息来判断是否真的是连接上了,没有连接上的时候还能给出发生了什么错误,当然我程序中并没有标出那么多状态,只是简单的表示可连接/不可连接。下面我来谈谈对这个程序测试的结果。我针对3种情形做了测试:1. 目标机器网络正常的情况可以连接到目标主机,并能成功以阻塞方式进行发包收包作业。2. 目标机器网络断开的情况在等待设置的超时时间(上面的程序中为20秒)后,显示目标主机不能连接。3. 程序运行前断开目标机器网络,超时时间内,恢复目标机器的网络在恢复目标主机网络连接之前,程序一只等待,恢复目标主机后,程序显示连接目标主机成功,并能成功以阻塞方式进行发包收包作业。以 上各种情况的测试结果表明,这种设置connect超时的方法是完全可行的。我自己是把这种设置了超时的connect封装到了自己的类库,用在一套监控 系统中,到目前为止,运行还算正常。这种编程实现的connect超时比起修改系统参数的那种方法的有点就在于它只用于你的程序之中而不影响系统。connect非阻塞套接口时候,一般使用在以下几种情况: 1.三路握手需要时间,这个要视具体的网络情况而定。当然也有可能失败。在三路握手的时候我们并不需要在原地等待三路握手的完成,可以用这些时间来 完成其它事情,然后当这些事情完成后,再去检测连接是否建立(也就是三路握手是否完成)。 2.可以用这种技术来同时建立多个连接。(WEB浏览器中很常用)。 3.connect超时需要很长时间才会通知,如果我们认为超过0.1秒以后就算超时(不管它是不是真的超时),这是就可以使用非阻塞式I/O结合 select来完成。 当采用非阻塞式I/O来使用connect时候,要判断一个连接是否建立则比较复杂,需要按照以下几个步骤来完成 1.即使是使用非阻塞式的connect操作,connect依然可能正确返回,也就是说非阻塞的connect 也有可能三路连接完成后返回,这种情况一般发生在服务器和主机在同一个机器上,所以第一步要判断connect是否正确返回,如果正确返回则请做正确返回 的处理,否则进入步骤2 2.设置fd_set,(如果没看明白,请先看select函数介绍),让select函数同时监听套接字的读写2个属性,如果既可读也可写则进入 步骤3,如果可写但不可读进入步骤4. 3.如果到达这步,我们需要调用getsockopt进一步判断。这里涉及到一个移植问题,getsockopt如果发生错误, 源自Berkeley的实现会返回0,如果是solaris,则会返回-1。建议是2个都处理(如果看不明白请先看getsockopt函数,套接口选 项)。根据getsockopt通过参数返回的erron的值,如果值为0则表示链接建立完成,如果不为0, 则说明链接建立没有完成。 4.如果能到达这里,则说明连接建立完成。 最后,即使最后你得出链接没有建立完成,也只是说:可能三路握手的过程还是没有完成。 代码:服务器#include "/programe/net/head.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#define MAXSIZE 100//如果这样写,最后返回的套接口应该是会进入步骤3,也就是套接口既可读也可写,如果想进入步骤4,就不要想套接口中写入数据int main(int argc, char ** argu) { int listenfd, connfd; struct sockaddr_in servaddr; char buf[MAXSIZE + 1]; char buf2[] = "hello world\n"; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argu[1])); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 10); for(;;) { connfd = accept(listenfd, (struct sockaddr *)NULL, NULL); write(connfd, buf2, sizeof(buf2)); close(connfd); }} 客户端#include "/programe/net/head.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "unistd.h"#include "fcntl.h"#include "sys/select.h"#define MAXSIZE 100int main(int argc, char ** argv) { int sockfd, n; int my; char send_buf[MAXSIZE + 1]; char recv_buf[MAXSIZE + 1]; struct sockaddr_in servaddr; int error = 0; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("create socket error\n"); exit(1); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(atoi(argv[1])); if(inet_pton(AF_INET, "192.168.1.235" , &servaddr.sin_addr) < 0) { printf("inet_pton error\n"); exit(1); } int val = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, val O_NONBLOCK); //设置套接口非阻塞 int connect_flag = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)); sleep(2); //connect会立即返回,不同于之前的要阻塞到链接完成才会返回,这里可以做你想在等待连接完成的时间想做的事情,我这里只是让进程睡眠了一段时间 if(connect_flag >= 0) { printf("connect success\n"); //即使是非阻塞套接口,connect还是有可能正确返回的,这种情况要处理 goto done; //不建议使用goto } fd_set rest, west; FD_ZERO(&rest); FD_ZERO(&west); FD_SET(sockfd, &rest); FD_SET(sockfd, &west); int maxpd = sockfd + 1; int flag = select(maxpd, &rest, &west, NULL, NULL);//监听套接的可读和可写条件 if(flag < 0) { printf("select error\n");//慢系统调用可能会错误返回,这个以前提过 exit(1); } if(FD_ISSET(sockfd, &rest) && FD_ISSET(sockfd, &west)) {//如果套接口及可写也可读,需要进一步判断 socklen_t len = sizeof(error); if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) exit(1);//获取SO_ERROR属性选项,当然getsockopt也有可能错误返回 printf("error = %d\n", error); if(error != 0) {//如果error不为0, 则表示链接到此没有建立完成 printf("connect failed\n"); exit(1); } //如果error为0,则说明链接建立完成 } if(FD_ISSET(sockfd, &west) && !FD_ISSET(sockfd, &rest)) { //如果套接口可写不可读,则链接完成 printf("connect success\n"); }done: int recv_buf_len = read(sockfd, recv_buf, MAXSIZE); recv_buf[recv_buf_len] = '\0'; printf("get message:%s", recv_buf); close(sockfd); exit(0);
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
宜宾陪产假有多少天 ...19宽屏显示器。调色彩时有个选项magicColor是什么意思? eternuer是什么意思 《法语助手》法汉 癌症老人能吃山竹吗 癌症病人能吃抗氧化剂吗 乳腺癌骨转移病人吃什么水果好 肝癌老人吃山竹有害处吗 癌症病人能不能吃山竹 如何在excel中批量加入数据 在Excel中怎样批量加上一? 请问现在香樟是不是保护植物? 韩寒和韩雪是什么关系? 中国古代历史上名相,你了解多少 红萝卜31:百度图片里搜“韩雪”,出来的好像不是同一个人啊,有几个... 联想h3050 i54460,想换个显卡,求推荐 联想H3050 i5-4460 4G 500G 1G独显 DVD 千兆网卡 Win8.1能换讯景HD7850... lenovo h3050 能换GTX950吗 怎样和顾客交流8 如何对消费者进行直接说服和间接说服2 直接销售与间接销售的方式各是什么?25 edge浏览器怎么打开网页翻译功能 edge浏览器翻译在哪 微信手机号在24小时内,已绑定两个,已达到限制,不能在绑定其他微信... 梦见包破了漏了 辞旧迎新的古诗词元日 整改落实情况的报告 沈阳有个诚大冷库,据说仓储55000吨,条件和服务都很不错,在于洪区... 软考论文 能否出现实际的单位名称 论文中可以出现真实的公司名称吗 微信手机号在24小时内,已绑定两个,已达到限制,不能在绑定其他微信... 中文杨...小龙。用英文翻译过来怎么写。尤其是小龙。拜托大家了_百度知 ... word中的临时文件在哪儿,怎样删除 ...职业性.规范性.哪些属于社会主义职业道德的特征 乔依宋骁的小说推荐 linux connect是不是完成了三次握手 用i9新款CPU,+一个强大点的独立显卡配一个主机。多少钱不计较,谁能给... P.R.C ??? P.R.C. ??? l,o,u,o,r,c 组成一个单词 小小的动词都有哪些? 你知道哪些励志的句子吗?这十六句哪一句触动你最深? 的地得的用法专业点 公司不缴纳五险一金是违法的吗 ...贷款还不了解政策,今年太原的住房公积金贷款利率是多少啊 济南立和瑞隆安中医院逯祥云院长治疗心脑血管病怎么样? 微信手机号在24小时内,已绑定两个,已达到限制,不能在绑定其他微信... 在酒店内如果遇到客人用了东西但是拒不承认怎么办 纽约有哪些特色小吃值得品尝? 康佳电视LED42×1800A需要什么样的内存卡???怎么卡槽那么大?另外我用其... rpg游戏卡在nowloading 安装的鬼泣4打开后出现NOW LOADING...什么情况?