int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数:

  • nfds:监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件文件描述符
  • readfs:监控有读数据到达文件描述符集合,传入传出参数
  • writefds:监控写数据到达文件描述符集合,传入传出参数
  • exceptfds:监控异常发生到达文件描述符集合,如带外数据到达异常,传入传出参数
  • timeout:定时阻塞监控时间。
#include <sys/select.h>
void FD_CLR(int fd, fd_set *set);     // 把文件描述符集里fd位清0
int  FD_ISSET(int fd, fd_set *set);   // 测试文件描述符集里fd是否置1
void FD_SET(int fd, fd_set *set);     // 把文件描述符集合里fd位置1
void FD_ZERO(fd_set *set);            // 把文件描述符集合里所有位清0

二、select函数用法图解

三、实验一

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>void perr_exit(const char *s)
{perror(s);exit(-1);
}int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{int n;again:if ((n = accept(fd, sa, salenptr)) < 0) {//ECONNABORTED 发生在重传(一定次数)失败后,强制关闭套接字//EINTR 进程被信号中断if ((errno == ECONNABORTED) || (errno == EINTR)){goto again; }else{perr_exit("accept error");}}return n;
}int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{int n;if ((n = bind(fd, sa, salen)) < 0){perr_exit("bind error");}return n;
}int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{int n;n = connect(fd, sa, salen);if (n < 0) {perr_exit("connect error");}return n;
}int Listen(int fd, int backlog)
{int n;if ((n = listen(fd, backlog)) < 0){perr_exit("listen error");}return n;
}int Socket(int family, int type, int protocol)
{int n;if ((n = socket(family, type, protocol)) < 0){perr_exit("socket error");}return n;
}ssize_t Read(int fd, void *ptr, size_t nbytes)
{ssize_t n;again:if ( (n = read(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}ssize_t Write(int fd, const void *ptr, size_t nbytes)
{ssize_t n;again:if ((n = write(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n;
}int Close(int fd)
{int n;if ((n = close(fd)) == -1)perr_exit("close error");return n;
}
#ifndef __WRAP_H_
#define __WRAP_H_void perr_exit(const char *s);
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
int Listen(int fd, int backlog);
int Socket(int family, int type, int protocol);
ssize_t Read(int fd, void *ptr, size_t nbytes);
ssize_t Write(int fd, const void *ptr, size_t nbytes);
int Close(int fd);
ssize_t Readn(int fd, void *vptr, size_t n);
ssize_t Writen(int fd, const void *vptr, size_t n);
ssize_t my_read(int fd, char *ptr);
ssize_t Readline(int fd, void *vptr, size_t maxlen);#endif
  • 服务端server.c
//server.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/select.h>
#include "wrap.h"#define SERV_PROT 6666int main(int argc, char *argv[])
{int i, j, n, nread;int maxfd = 0;int listenfd, connfd;char buf[BUFSIZ];struct sockaddr_in clie_addr, serv_addr;socklen_t clie_addr_len;listenfd = Socket(AF_INET, SOCK_STREAM, 0);int opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(SERV_PROT);Bind(listen, (struct sockaddr*)&serv_addr, sizeof(serv_addr));Listen(listenfd, 128);fd_set rset, allset;maxfd = listenfd;FD_ZERO(&allset);FD_SET(listenfd, &allset);while (1){rset = allset;nread = select(maxfd + 1, &rset, NULL, NULL, NULL);  //每次循环都从新设置select监控信号集if(nread < 0)perr_exit("select error");if (FD_ISSET(listenfd, &rset))   //说明有新的客户端连接请求{clie_addr_len = sizeof(clie_addr);connfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);FD_SET(connfd, &allset); //向监控文件描述符集合allset添加新的文件描述符connfdif (maxfd < connfd)maxfd = connfd;if (0 == --nread)  //说明select只返回一个,并且listenfd,后续执行无须执行continue;}for (i = listenfd + 1; i <= maxfd; i++){if (FD_ISSET(i, &rset)){if ((n = Read(i, buf, sizeof(buf))) == 0)  //当client关闭链接时, 服务端也关闭对应链接{Close(i);FD_CLR(i, &allset);  //解除select对此文件描述符的监控}else if(n == -1)perr_exit("read error");for (j = 0; j < n; ++j)buf[j] = toupper(buf[j]);Write(i, buf, n);}}}Close(listenfd);return 0;
}
  • 客户端:clent.c
#include <arpa/inet.h>
#include "wrap.h"#define SERV_IP "192.168.245.139"
#define SERV_PORT 6666int main(void)
{int sfd, len;struct sockaddr_in serv_addr;char buf[BUFSIZ];sfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);serv_addr.sin_port = htons(SERV_PORT);Connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));while (1) {fgets(buf, sizeof(buf), stdin);int r = Write(sfd, buf, strlen(buf));printf("Write r ======== %d\n", r);len = Read(sfd, buf, sizeof(buf));printf("Read len ========= %d\n", len);Write(STDOUT_FILENO, buf, len);}Close(sfd);return 0;
}
  • 公共头文件集程序:wrap.h、wrap.c

输出结果:

客户端:

服务端:

select函数(一)相关推荐

  1. R语言dplyr包使用select函数通过索引查询或者排除数据列实战(Select Columns by Index)

    R语言dplyr包使用select函数通过索引查询或者排除数据列实战(Select Columns by Index) 目录

  2. socket通信时如何判断当前连接是否断开--select函数,心跳线程,QsocketNotifier监控socket...

    client与server建立socket连接之后,如果突然关闭server,此时,如果不在客户端close(socket_fd),会有不好的影响: QsocketNotifier监控socket的槽 ...

  3. 关于select函数

    1.阻塞模式下必须开多线程来解决阻塞问题,但是为每个socket开了多线程后,多线程的运行开销很大,速度超级慢. 如果,多线程的速度能跟得上,那是非常不错.但是事实上可能并非如此. 2.因此selec ...

  4. UNIX中的Select函数

    表头文件 #i nclude<sys/time.h> #i nclude<sys/types.h> #i nclude<unistd.h> 定义函数 int sel ...

  5. select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型, 原型: int select(int maxfd,fd_set *rds ...

  6. form select multiple 某个字段是数组_你知道什么是Select函数吗?

    Select函数:允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生或经历一段指定的时间后才唤醒它. select man手册 举个栗子,我们可以调用Select,告诉内核仅仅在 ...

  7. linux 下 select 函数的用法

    一.Select 函数详细介绍 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv ...

  8. SOCKET编程中,select()函数的作用

    SOCKET编程中,select()函数的作用Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accep ...

  9. 多路 IO 转接 :select 函数

    (1)头文件: #include <sys/select.h> (2)函数原型: int select( int nfds, fd_set *readfds, fd_set *writef ...

  10. step5 . day6 网络编程 基于TCP协议的多并发模式(使用多进程、多线程、select函数分别实现)...

    实现TCP服务器端多路并发的方法有①多进程②多线程③IO多路复用(select poll epoll函数) 1.多进程实现并发模式(仅在服务器端更改之前代码实现) 服务器端 #include < ...

最新文章

  1. 高精地图:为自动驾驶汽车提供动力的新时代地图
  2. 我有个师兄,毕业后投身了学术自媒体行业
  3. LightGBM和XGBoost使用scale_pos_weight处理不平衡数据源码分析
  4. CF 287(div 2) B Amr and Pins
  5. UA OPTI501 电磁波 经典电动力学中的Fourier方法基础
  6. rubymine 保存成unix格式_如何免费在线试用 200+ Linux 和 Unix 发行版?
  7. PHP直接输出一张图片
  8. django3数据库设计之商城项目
  9. python getattr用法_python3,定制类,getattr相关用法
  10. [转]MTK android 下载及启动过程
  11. 小米MAX Root,第三方REC,XP框架刷入
  12. oracle 方法函数,执行oracle函数的四种方法
  13. 计算机网络实验指导书 pdf,《计算机网络》实验指导书.pdf
  14. 戴尔笔记本插耳机听歌暂停后继续声音突然变大
  15. 2 Linux内核目录概述
  16. C#:base64解码显示
  17. cin、cout、cerr、clog用法区别及其在VS环境下的重定向
  18. 大数据面试杀招 | Flink,大数据时代的“王者”
  19. 火车硬座车厢座位分布表
  20. 一般人不清楚的JavaScript概念

热门文章

  1. .NET通用基本权限系统
  2. 单击浏览器右上角的X弹出提示窗口
  3. Mapx的VC开发实践
  4. 如何用python写html的插件,使用python开发vim插件及心得分享
  5. 海洋主题绘画_深圳举办风帆时代海洋绘画作品展,展出作品600余件
  6. php注册登录遍写入 遍验证,自动注册登录验证机制的php代码
  7. mysql查询某张表的所有外键_oracle中查询所有外键引用到某张表的记录
  8. linux nfsnobody用户,处理CentOS 5.5 x64 配置NFS服务过程中nfsnobody用户造成的问题
  9. c++ 多重背包状态转移方程_动态规划入门——详解经典问题零一背包
  10. win10资源管理器怎么打开_让你效率倍增的电脑神器,最强资源管理器增强工具「QTTabBar」...