c++ select 返回值函数返回值-1只能重启么

新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 5, 距离下一级还需 195 积分
论坛徽章:0
DESCRIPTION
& && & select() and&&pselect()&&allow&&a&&program&&to&&monitor&&multiple&&file
& && & descriptors,&&waiting&&until one or more of the file descriptors become
& && & &ready& for some class of I/O operation (e.g., input possible).&&A file
& && & descriptor&&is considered ready if it is possible to perform the corre‐
& && & sponding I/O operation (e.g., read(2)) without blocking.
以上是手册上对select函数的描述,其中说到的监视多个文件描述符,但是阻塞返回却是一个或多个文件描述符“就绪”。我的疑问就是内核怎么才会将多个文件描述符的行为定性为多个同时“就绪”并返回,理论上来说总得有个先后啊,难道是第一个“就绪”发生后等待了一段时间?
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
大富大贵, 积分 19093, 距离下一级还需 907 积分
论坛徽章:11
select 唤醒和描述符发生事件是异步的, 因此, 当 select 唤醒后, 未必只有一个描述符上存在事件; 你也可以认为它等了一会儿; 等待的时间就是从睡眠到运行态转换的时间, 或者也可以认为是多个描述符同时产生了事件, 这也不是不可能的
白手起家, 积分 5, 距离下一级还需 195 积分
论坛徽章:0
zylthinking
嗯,原来还要结合进程运行状态切换来理解,谢谢。
巨富豪门, 积分 38219, 距离下一级还需 1781 积分
论坛徽章:4
lyush 发表于
回复 2# zylthinking
嗯,原来还要结合进程运行状态切换来理解,谢谢。
你select会发生系统调用陷入到内核执行,在内核里发现所有描述符都不可读写就会将这个进程改为挂起状态并调度其他进程到CPU工作。
网卡的硬件中断触发(超时或者先攒着)或者硬件时钟中断(超时或者批量返回)都会给内核检查与重新唤醒select进程的机会。
家境小康, 积分 1281, 距离下一级还需 719 积分
论坛徽章:1
select本身可能是会阻塞的,但阻塞后会让该进程挂起,不占用CPU的时间片。
select函数返回了,该进程才可能再次运行。
白手起家, 积分 4, 距离下一级还需 196 积分
论坛徽章:0
意思是select的目的是监视改变了的文件描述符。在休眠时,来了一个或者同时来了多个小伙伴(改变的文件描述符)都能把select唤醒。他们的到来是异步的,每个都是随时可能发生的,可能某时刻来了一个或者同时来了几个。
zylthinking 发表于
回复 1# lyush
select 唤醒和描述符发生事件是异步的, 因此, 当 select 唤醒后, 未必只有一个描述符 ...
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
丰衣足食, 积分 951, 距离下一级还需 49 积分
论坛徽章:1
#include&stdio.h&
#include &stdlib.h&
#include&strings.h&
#include &string.h&
#include&unistd.h&
#include&sys/types.h&
#include&sys/socket.h&
#include&netinet/in.h&
#include&arpa/inet.h&
#include&pthread.h&
#define PORT 4502
#define BACKLOG 1
#define MAXDATASIZE 4000
#define ONLINE 8000 /*定义一个最大5000人在线的情况*/
#define&&PTHREAD_THREADS_MAX& &50 /*允许一个进程创建这个数量的线程*/
struct ARG
& & int connfd[ONLINE][6]; //用户信息列表 数字型
& & char *connfds[ONLINE][20]; //用户信息列表 字符串型
& & int currently,pthread_id[PTHREAD_THREADS_MAX];
& & struct sockaddr_
& &//下一个线程
////////////////////////////////////////
void *func(void *arg );
int simulate_accept(void *arg,int pt);
int acceptfz(void *arg,int client_fd,int e);
///////////////////////////////////
int main()
& &&&pthread_
& & pthread_attr_
& &&&int listenfd,i,
& &&&struct sockaddr_
& &&&struct sockaddr_
& &&&socklen_
& &&&char buf[MAXDATASIZE];
& &&&struct ARG *arg,
& &&&arg = &
& & printf(&初始化数据\n"
& & for (i=0;i&ONLINE;i++)
& && && &//初始化在线人数
& && &&&arg-&connfd[0]=0;//连接句柄
& && &&&arg-&connfd[1]=0;//联盟ID
& && &&&arg-&connfd[2]=0;//门派ID
& && &&&arg-&connfd[3]=0;//是否允许登陆0为不允许
& && &&&arg-&connfd[4]=0;//使用那个线程
& && &&&arg-&connfd[5]=0;//是否已经加入select的句柄集
& && &&&arg-&connfds[0]=(char*)&&;//昵称
& && &&&arg-&connfds[1]=(char*)&&;//玩家用户名
& & arg-&pth=100;
& & printf(&启动线程\n"
& & pthread_attr_init(&attr);
& & pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS);//把线程脱离出去
& & pthread_attr_setstacksize(&attr,512);//线程堆贱大小
& &&&for(i=0;i&THREAD_THREADS_MAX;i++)
& && && && &//创建50个应用线程
& && && &if(pthread_create(&tid,&attr, func, (void *)arg))
& && && &{
& && && && &&&perror(&error pthread_create2"
& && && &}
& && &&&printf(&启动处理线程%d\n&,tid);
& && &&&arg-&pthread_id=//取得线程ID
& & printf(&建立socket\n"
& &&&if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
& && &&&perror(&socket() error."
& && &&&//exit(1);
& &&&int opt = 1;
& &&&setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
& &&&bzero(&server, sizeof(server));
& &&&server.sin_family = AF_INET;
& &&&server.sin_port = htons(PORT);
& &&&server.sin_addr.s_addr = htonl(INADDR_ANY);
& &&&if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)
& && && & perror(&bind() error."
& && && & //exit(1);
& &&&if(listen(listenfd, BACKLOG) == -1)
& && && & perror(&listen() error."
& && && & //exit(1);
& &&&printf(&主程序进入守护状态\n"
& &&&addrlen = sizeof(client);
& &&&while(1)
& && && &if((arg-&currently= accept(listenfd, (struct sockaddr *)&client, &addrlen )) == -1)
& && && &{
& && && && &&&perror(&accept() error."
& && && && &&&//exit(1);
& && && &}
& && &&&acceptfz(arg,arg-&currently,1);//像socket注册句柄
& & return 0;
void *func(void *arg)
& & //便利属于这个线程的100个用户
& & //pthread_detach(pthread_self());//上面已经把这个线程分离出来啦
& & struct ARG *
& & args =&&(struct ARG *)
& & int retval,i,j,pt=pthread_self();//取得线程ID
& & int in=0;
& & char *tmp[20];
& & char*bufs = (char *) malloc ( sizeof(int) *MAXDATASIZE);
& & int oks=0,maxfd=-1;
& & maxfd = 0;
& & while(1)
& && && && &i=simulate_accept(args,pt);//返回用户下标
& && && && &printf(&句柄分析 %i-------用户序列号:%i\n&,args-&connfd[0],i);
& && && && &//提取出属于自己线程的句柄,并且句柄不能为0
& && && && &
& && && && &//是否加入集合中
& && && && &if(args-&connfd[5]==0)
& && && && &{
& && && && && & //把集合清空
& && && && && & FD_ZERO(&rfds);
& && && && && & // 把当前连接句柄new_fd加入到集合中
& && && && && & FD_SET(args-&connfd[0], &rfds);
& && && && && & args-&connfd[5]=1;
& && && && && & printf(&已将句柄 %i 加入到集合中----%i\n&,args-&connfd[0],i);
& && && && &}
& && && && &
& && && && &if (args-&connfd[0] & maxfd)
& && && && &{
& && && && && & maxfd = args-&connfd[0];
& && && && &}
& && && && &// 设置最大等待时间
& && && && &tv.tv_sec = 0;
& && && && &tv.tv_usec =100;
& && && && &//printf(&最大句柄----%i\n&,maxfd);
& && && && &// 开始等待
& && && && &retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
& && && && &if (retval == -1)
& && && && &{
& && && && && & perror(&select error."
& && && && && &
& && && &&&} else if (retval == 0) {
& && && && && &//printf(&没有任何消息到来,继续等待……%i\n&,i);
& && && && && &
& && && && &} else {
& && && && && & printf(&有一个操作信号\n&);
& && && && && & if (FD_ISSET(args-&connfd[0], &rfds))
& && && && && & {
& && && && && && && && &memset(bufs, 0, MAXDATASIZE);
& && && && && && && && &memset(tmp, 0, 20);
& && && && && && && && &
& && && && && && && && & if (read(args-&connfd[0], bufs, MAXDATASIZE)& 0)
& && && && && && && && &{
& && && && && && && && && && &&&perror(&read error&);
& && && && && && && && && && &&&acceptfz(args,args-&connfd[0],0);
& && && && && && && && && && &&&close(args-&connfd[0]);
& && && && && && && && && && &&&//exit(0);
& && && && && && && && && && && &
& && && && && && && && &}
& && && && && && && && &
& && && && && && && && &printf(&读取客户端信息: %s\n&,bufs);
& && && && && & }
& && && && &}
//将accept加入到用户列表中或注销
int acceptfz(void *arg,int client_fd,int e)
& & struct ARG *
& & info =&&(struct ARG *)
& & if(e==1)
& && &&&for(j=0;j&ONLINE;j++)
& && && && && & //找一个空的句柄存储仓
& && && && && & if(info-&connfd[j][0]==0)
& && && && && & {
& && && && && && &&&//将句柄交给存储仓
& && && && && && &&&info-&connfd[j][0]=client_//句柄注册
& && && && && &
& && && && && && &&&//为句柄分配线程号
& && && && && && &&&if(info-&pth==100 || info-&pth==PTHREAD_THREADS_MAX)
& && && && && && &&&{
& && && && && && && && &info-&pth=1;
& && && && && && && && &info-&connfd[j][4]=info-&pthread_id[0];//初始化第一个
& && && && && && &&&}else{
& && && && && && && && &info-&connfd[j][4]=info-&pthread_id[info-&pth];
& && && && && && && && &printf(&新线程号:%i--------pth:%i\n&,info-&pthread_id[info-&pth],info-&pth);
& && && && && && && && &info-&pth++;
& && && && && && &&&}
& && && && && &
& && && && && && &&&printf(&将连接句柄交给%s:%i,线程号:%i\n&,&connfd&,info-&connfd[j][0],info-&connfd[j][4]);
& && && && && && &&&
& && && && && & }
& & }else{
& && &&&for(j=0;j&ONLINE;j++)
& && && && &if(info-&connfd[j][0]==client_fd)
& && && && &{
& && && && && & printf(&用户:%i连接被销毁\n&, info-&connfd[j][0]);
& && && && && &
& && && && && & info-&connfd[j][0]=0;
& && && && && & info-&connfd[j][1]=0;
& && && && && & info-&connfd[j][2]=0;
& && && && && & info-&connfd[j][3]=0;
& && && && && & info-&connfd[j][4]=0;
& && && && && & info-&connfd[j][4]=0;
& && && && &
& && && && && & info-&connfds[j][0]=&&;
& && && && && & info-&connfds[j][1]=&&;
& && && && && &
& && && && && & pthread_exit((char*)pthread_self());//销毁线程释放内存
& && && && && &
& && && && &}
& & return 0;
int simulate_accept(void *arg,int pt)
& & struct ARG *
& & args =&&(struct ARG *)
& & int i,j,oks=0;
& & //int j = (int ) malloc (sizeof(int)* 5);
& & for(i=0;i&-1;i++)
& && &&&if(i==ONLINE){i=0;}
& && && && &
& && &&&for (j=0;j&ONLINE;j++)
& && && && &if(args-&connfd[j][4]==pt && args-&connfd[j][0]!=0 && args-&connfd[j][5]==0)
& && && && &{
& && && && && & printf(&已经检查到一个新句柄 %i----用户序列号:%i----是否在集合中%i\n&,args-&connfd[j][0],j,args-&connfd[j][5]);
& && && && && &
& && && && &}
& && &&&if(oks==0)
& && &&&{//句柄列表中是否有有效的连接
& && && && &//printf(&线程处于等待状态%d\n&,pt);
& && && && &sleep(1);
& && && && &
代码我是提取出来的,帮我看看逻辑是否有问题,我是新学C的,忘高手帮忙看下为什么select检查不到我前台发送过来的数据(就是read给没被执行到郁闷,连接正常)。
这个是我自己写的,我的思路是想让一个线程守候端口,如果有客户端连接则忘一个数组里把这个句柄加入到数组中,
然后其他50个线程就处理这个数组中的数据,acceptfz函数在守候线程里就开始分配句柄属于那个线程的
[ 本帖最后由 jd808 于
16:18 编辑 ]
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
丰衣足食, 积分 951, 距离下一级还需 49 积分
论坛徽章:1
没人给个意见??
稍有积蓄, 积分 333, 距离下一级还需 167 积分
论坛徽章:0
代码太长了
丰衣足食, 积分 951, 距离下一级还需 49 积分
论坛徽章:1
这是一个基本的呀,在精简了你们就找不到问题所在,而且还不知道代码到底是干什么的
小富即安, 积分 2665, 距离下一级还需 2335 积分
论坛徽章:0
程序有够乱的,这么简单的功能写出这么复杂的代码来。你的线程中是不是可以select多个socket?那你每得一个新的之后好像就FD_ZERO了,只有一个。另外看如下判断:
& && && && &//是否加入集合中
&&&&&&&&&&&&if(args-&connfd[5]==0)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&//把集合清空
&&&&&&&&&&&&&&&&FD_ZERO(&rfds);
&&&&&&&&&&&&&&&&// 把当前连接句柄new_fd加入到集合中
&&&&&&&&&&&&&&&&FD_SET(args-&connfd[0], &rfds);
&&&&&&&&&&&&&&&&args-&connfd[5]=1;
&&&&&&&&&&&&&&&&printf(&已将句柄 %i 加入到集合中----%i\n&,args-&connfd[0],i);
&&&&&&&&&&&&}
如果这段代码不是每次都执行那问题就来了,select的几个文件句柄集合都是In-Out参数,一旦超时一次集合中全部为空。
丰衣足食, 积分 951, 距离下一级还需 49 积分
论坛徽章:1
大哥 代码不简单啊,里面很多功能我只是把代码抽取出来才显得比较乱的
上面那段代码是否执行要看&&
i=simulate_accept(args,pt);
当他接收到一个新的句柄之后就返回(属于本线程的),否者就一直挺在这里呢 与真正的accept效果差不多的方式。
不然的话 func 函数可能就一直处于死循环很消耗cpu呢
当然前面的程序把接到的句柄分配给这个线程的时候,而这个线程见到有新的句柄加入就会执行下面,那个args-&connfd[5]是用来判断是否已经加入到集合中,这个其实在simulate_accept函数里我已经判断过的,
分配句柄交给那个线程处理是油 acceptfz(arg,arg-&currently,1);
函数处理,这些还数我都贴出,带回我把他弄成彩色的加在下面方便你们观看
if(args-&connfd[5]==0)
& & //把集合清空
& & FD_ZERO(&rfds);
& & // 把当前连接句柄new_fd加入到集合中
& & FD_SET(args-&connfd[0], &rfds);
& & args-&connfd[5]=1;
& & printf(&已将句柄 %i 加入到集合中----%i\n&,args-&connfd[0],i);
[ 本帖最后由 jd808 于
16:14 编辑 ]
家境小康, 积分 1716, 距离下一级还需 284 积分
论坛徽章:0
最好是用一个变量来存rfds的值。
然后才传给select,
因为select执行后会改娈rfds的值。你最好再去了解一下select是如何工作的。
我没也没仔细看你的代码,因为太长了。
[ 本帖最后由 xieweihua 于
16:13 编辑 ]
丰衣足食, 积分 951, 距离下一级还需 49 积分
论坛徽章:1
发不了彩色的 没办法说太长了,在说了分太多次发你们也不定看的舒服
[ 本帖最后由 jd808 于
16:17 编辑 ]
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处细谈select函数(C语言) - CSDN博客
细谈select函数(C语言)
&&&&&&Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况&&读写或是异常。
Select的函数格式:
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*timeout); 先说明两个结构体: 第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来操作,比如清空集合FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set*),将一个给定的文件描述符从集合中删除FD_CLR(int,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。
第二,struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。 具体解释select的参数: int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。 fd_set * readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。 fd_set * writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。 fd_set * errorfds同上面两个参数的意图,用来监视文件错误异常。 struct timeval * timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。 返回值:返回状态发生变化的描述符总数。 负值:select错误
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
select举例:
①读取键盘输入值,超时间隔2.5秒,输出用户输入的字符个数。
#include &sys/types.h&
#include &sys/time.h&
#include &stdio.h&
#include &fcntl.h&
#include &sys/ioctl.h&
#include &unistd.h&
int main()
char buffer[128];
int result,
fd_set inputs,
FD_ZERO(&inputs);//用select函数之前先把集合清零
FD_SET(0,&inputs);//把要检测的句柄&&标准输入(0),加入到集合里。
timeout.tv_sec = 2;
timeout.tv_usec = 500000;
result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
switch(result)
printf("timeout/n");
perror("select");
if(FD_ISSET(0,&testfds))
ioctl(0,FIONREAD,&nread);//取得从键盘输入字符的个数,包括回车。
if(nread == 0)
printf("keyboard done/n");
nread = read(0,buffer,nread);
buffer[nread] = 0;
printf("read %d from keyboard: %s", nread, buffer);
②利用select而不是fork来解决socket中的多客户问题。
服务器端:
#include &sys/types.h&
#include &sys/socket.h&
#include &stdio.h&
#include &netinet/in.h&
#include &sys/time.h&
#include &sys/ioctl.h&
#include &unistd.h&
int main()
int server_sockfd, client_
int server_len, client_
struct sockaddr_in server_
struct sockaddr_in client_
fd_set readfds,
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立服务器端socket
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);//将服务器端socket加入到集合中
printf("server waiting/n");
/*无限期阻塞,并测试文件描述符变动 */
result = select(FD_SETSIZE, &testfds, (fd_set *)0,(fd_set *)0, (struct timeval *) 0);
if(result & 1)
perror("server5");
/*扫描所有的文件描述符*/
for(fd = 0; fd & FD_SETSIZE; fd++)
/*找到相关文件描述符*/
if(FD_ISSET(fd,&testfds))
/*判断是否为服务器套接字,是则表示为客户请求连接。*/
if(fd == server_sockfd)
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
FD_SET(client_sockfd, &readfds);//将客户端socket加入到集合中
printf("adding client on fd %d/n", client_sockfd);
/*客户端socket中有数据请求时*/
ioctl(fd, FIONREAD, &nread);//取得数据量交给nread
/*客户数据请求完毕,关闭套接字,从集合中清除相应描述符 */
if(nread == 0)
close(fd);
FD_CLR(fd, &readfds);
printf("removing client on fd %d/n", fd);
/*处理客户数据请求*/
read(fd, &ch, 1);
printf("serving client on fd %d/n", fd);
write(fd, &ch, 1);
#include &sys/types.h&
#include &sys/socket.h&
#include &stdio.h&
#include &netinet/in.h&
#include &arpa/inet.h&
#include &unistd.h&
int main()
int client_
struct sockaddr_//服务器端网络地址结构体
char ch = 'A';
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立客户端socket
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(&127.0.0.1&);
address.sin_port = 9734;
len = sizeof(address);
result = connect(client_sockfd, (struct sockaddr *)&address, len);
if(result == -1)
perror("oops: client2");
write(client_sockfd, &ch, 1);
read(client_sockfd, &ch, 1);
printf("char from server = %c/n", ch);
close(client_sockfd);
本文已收录于以下专栏:
相关文章推荐
Select函数在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、 accept、recv或recvfrom这样的阻塞...
1.表头文件
2.函数原型
int select(int n,fd_set * readfds,fd_set * writefds,fd_s...
前面两篇介绍用进程方式和线程方式实现并发服务,其实里面调用send,read,accept函数都会导致阻塞,而linux的select函数可以使我们在程序中同时监听多个文件描述符的读写状态。程序会停在...
http://blog.csdn.net/codejoker/article/details/5404442?locationNum=1
select 需要驱动程序的支持,驱动程序实现...
一、函数原型及参数说明
int select(int maxfdp, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct ...
在编程的过程中欧
Select函数在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect、 accept、recv或recvfrom这样的阻塞...
select函数使我们可以执行I/O多路转接。
传向select函数的参数告诉内核:
1 我们所关心的描述符。
2 对于每个描述符我们关心的条件(读,写,异常)
3 希望等待多长时间(永久等待,等一段...
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如
connect、accept、recv或recvfrom这样的阻塞...
原型int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,const struct timeval* timeo...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 mysql select 返回值 的文章

 

随机推荐