I/O多路转接之select


FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set*set);⽤用来设置描述词组set中相关fd的位

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<assert.h>
#include<unistd.h> int fds[];
const int back_log=;
void usage(char* argv)
{
printf("%s:[ip][port]\n",argv);
}
int start_up(char* ip,int port) //创建一个套接字,绑定,检测服务器
{
//sock
int sock=socket(AF_INET,SOCK_STREAM,); //创建套接字
if(sock<)
{
perror("sock");
exit();
}
struct sockaddr_in local; //本地 sockaddr_in 结构体
local.sin_port=htons(port);
local.sin_family=AF_INET;
local.sin_addr.s_addr=inet_addr(ip); //bind
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<) //绑定
{
perror("bind");
exit();
}
//listen
if(listen(sock,back_log)<) //检测服务器
{
perror("sock");
exit();
}
return sock;
}
int main(int argc,char* argv[])
{
if(argc!=) //检测参数个数是否正确
{
usage(argv[]);
exit();
}
int port=atoi(argv[]);
char* ip=argv[]; int done=;
int new_sock=-;
int listen_sock=start_up(ip,port); //创建一个绑定了本地 ip 和端口号的套接字描述符
struct sockaddr_in client;
socklen_t len=sizeof(client); int max_fd = -; //文件描述符最大值
fd_set _reads; //_reads文件描述符集
fd_set _writes; //_writes文件描述符集 int i=;
int fds_num=sizeof(fds)/sizeof(fds[]); //文件描述符的数组
for(i=;i<fds_num;i++) //初始化文件描述符数组
{
fds[i]=-;
}
fds[]=listen_sock; //将listen_sock写入文件描述符数组之中 while(!done)
{
FD_ZERO(&_reads); //每次循环把_reads,_writes初始化(输入、输出 参数)
FD_ZERO(&_writes);
struct timeval _timeout={,}; //设置等待时间
for(i=;i<fds_num;i++)
{
if(fds[i]>)
{
FD_SET(fds[i],&_reads); //select要监听的套接字描述符 加到文件描述符集中
if(fds[i]>max_fd)
{
max_fd=fds[i];
}
}
}
switch(select(max_fd+,&_reads,&_writes,NULL,&_timeout)) //_reads,_writes,_timeout 输入,输出参数
{
case : //select输出0 ,表示监听超时
printf("timeout\n");
break;
case -: //select出错
perror("select");
break;
default: //_reads(输入输出型参数)文件描述符集中有 OK 的
{
for(i=;i<fds_num;i++)
{
if(fds[i]==listen_sock&&FD_ISSET(fds[i],&_reads)) //select 关注的迎宾 socket 描述符已就绪
{
new_sock=accept(listen_sock,(struct sockaddr*)&client,&len); //创建新的 socket 描述符 if(new_sock<)
{
perror("new_sock");
continue;
}
printf("get connection...%ld\n",new_sock);
for(i=;i<fds_num;i++) //将新的 socket 描述符安排在数组中未被占用的最小位置
{
if(fds[i]==-)
{
fds[i]=new_sock;
break;
}
}
if(i==fds_num) //文件描述符个数已达到最大值则忽略
{
close(new_sock);
}
} else if(fds[i]>&&FD_ISSET(fds[i],&_reads)) //select 关注的普通的 socket 描述符
{
char buf[];
ssize_t _s=read(fds[i],buf,sizeof(buf)-);
if(_s>)
{
buf[_s]='\0';
printf("%s\n",buf);
}
else if(_s==)
{
fds[i] = -; //在 _read 文件描述符数组中去掉
printf("client closed\n");
}
else
{
perror("read");
}
}
else
{}
}
}
}
}
return ;
}
I/O多路转接之select的更多相关文章
- Linux下I/O多路转接之select --fd_set
fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...
- UNIX环境高级编程——I/O多路转接(select、pselect和poll)
I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.pselect ...
- 【Nginx】I/O多路转接之select、poll、epoll
当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...
- UNP——第六章,多路转接IO——select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ...
- 高级I/O之I/O多路转接——pool、select
当从一个描述符读,然后又写到另一个描述符时,可以在下列形式的循环中使用阻塞I/O: ) if (write(STDOUT_FILENO, buf, n) != n) err_sys("wri ...
- IO多路转接select和poll
select IO多路复用的设置方法与信号的屏蔽有点相似: 信号屏蔽需要先设定一个信号集, 初始化信号集, 添加需要屏蔽的信号, 然后用sigprocmask设置 IO多路转接需要先设定一个文件描述符 ...
- select函数与I/O多路转接
select函数与I/O多路转接 相作大家都写过读写IO操作的代码,例如从socket中读取数据可以使用如下的代码: while( (n = read(socketfd, buf, BUFSIZE) ...
- select 与 I/O多路转接
参考博客:http://blog.sina.com.cn/s/blog_607072980102uxcw.html I/0多路转接: 描述符表示某个I/O.构造一张有关描述符的数据表,调用select ...
- I/O多路转接 --- UNIX环境高级编程
I/O多路转接技术:先构造一张有关描述符的列表,然后调用一个函数,知道这些描述符中的一个已准备好进行I/O时,给函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.selec ...
随机推荐
- Welcome Back to C++ (Modern C++)
http://msdn.microsoft.com/en-us/library/hh279654.aspx 看看你是古代还是现代Cpper重点强调 Stack-based scope instead ...
- Bitmap 与Drawable相互转换
Drawable 转 Bitmap import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import ...
- [SSD大法好]神舟K480-I5-D3鸟枪换炮M6S
Hello,SSD 期盼已久,终于入手了M6S的256G固态硬盘,白天就不安生一直百度.谷歌.必应,势必要把所有相关消息查个清楚这神舟K480I5D3怎生拆呢. 最后心里隐约有了安装的法门. 但到得开 ...
- JavaScript高级程序设计6.pdf
ECMAScript通过RegExp类型来支持正则表达式 var expression=/pattern/flags;其中模式(pattern)部分是正则表达式,可以包含字符类.限定符.分组.向前查找 ...
- KiCad中层定义
5.2.1. Paired layers The Adhesives layers (Copper and Component): These are used in the applicati ...
- 基于curl 的zabbix API调用
1,认证并取得加密字段 curl -i -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0&q ...
- MenuDrawer的使用
---恢复内容开始--- MenuDrawer框架是一个可以实现上下左右滑动的框架,在使用中可以在xml文件中配置也可以在java代码中实现效果的配置 可以以jar的形式或依赖的形式存在 用 ...
- jump_ur.php通知模板
<title>出错啦~~~</title> <script language="javascript" type="text/javascr ...
- thinkphp xml编码函数
/** * XML编码 * @param mixed $data 数据 * @param string $root 根节点名 * @param string $item 数字索引的子节点名 * @pa ...
- tl;drLegal ——开源软件license的搜索引擎
TLDRLegal - Open Source Licenses Explained in Plain English可以很方便查询各个开源license的总结(能做什么,不能做什么),还能比较不同的 ...