网络服务器select
来源:互联网 发布:数字油画需要什么软件 编辑:程序博客网 时间:2024/06/11 22:59
select服务器的原理
select服务器实际上是对于用来标识文件描述符状态(“等”的状态结束 或正在“等”)的 fd_set变量 ret 进行检测(即select函数),对于已经完成“等”状态的文件描述符,即将开始I/O操作并不存在阻塞的问题,这样就大大提高了服务器运行效率
对于文件描述符集的操作函数有
FD_ZERO(fd_set* ret)
其功能: 初始化fd(标志位全部置0)
FD_SET(int fd, fd_set* ret)
其功能:设置描述词组ret中相关fd的位
FD_ISSET(int fd, fd_set* ret)
其功能:检测描述词组ret中相关fd的位是否被设置
FD_CLR(int fd, fd_set* ret)
其功能:清除描述词组ret中的相关fd的位
select函数
- 参数列表
select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout)
其中 nfds 是需要监视的最大的文件描述符+1
readfds、writefds、exceptfds分别代表可读文件描述符集合,可写文件描述符集合,异常文件描述符集合
timeout 用于描述一段时间长度,如果在这个时间内需要监视的文件描述符没有事件发生则函数返回0
重点:三个文件描述符集合都是输入输出型参数,作为输出时,返回对应事件就绪的文件描述符集,而select返回后会把以前加入的但并无事件发生的fd清空,基于这一点,我们必须另外创建某种数据结构来保存状态改变之前的文件描述符集的信息(代码中用一个数组来保存相应的信息)
- 返回值
执行成功返回文件描述符状态改变的个数
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <stdlib.h>#include <string.h>///////////////////static void usage(const char* pro){ printf("%s [local_ip][local_port]\n", pro);}//套接字的创建 绑定 和 设置监听状态,不做解释int startup(const char* _ip, int _port){ // chuangjian taojiezi int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0){ perror("socket"); exit(3); } // bangding struct sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(_port); local.sin_addr.s_addr = inet_addr(_ip); if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ perror("bind"); exit(4); } // jianting if(listen(sock, 10) < 0){ perror("listen"); } return sock;}//用于保存监视的文件描述符集int fd_array[sizeof(fd_set)*8];int main(int argc, char* argv[]){ if(argc != 3) { usage(argv[0]); return 1; } int listen_sock = startup(argv[1], atoi(argv[2])); int maxsz = sizeof(fd_array)/sizeof(fd_array[0]); int i = 0; //初始化数组,-1为无效值 for(; i< maxsz; i++) { fd_array[i] = -1; } fd_array[0] = listen_sock; while(1) { //创建文件描述符集,并初始化 fd_set fd; FD_ZERO(&fd); //用于标识nfds,即需要监视的最大的文件描述符值+1 int maxfd = -1; // for(i = 0; i < maxsz; ++i) { //set valid bit if(fd_array[i] == -1) continue; else { //将数组中有效的文件描述符添加监视 FD_SET(fd_array[i], &fd); //更新nfds if(maxfd < fd_array[i]) maxfd = fd_array[i]; } }//for结尾 // 初始化outime struct timeval outime = {5,0}; //只监视读事件 int s = select(maxfd+1, &fd, NULL, NULL, &outime); switch(s) { case 0: printf("no client ..\n"); break; case -1: perror("select"); break; default: { for(i=0;i<maxsz;++i) { if(fd_array[i] < 0) continue; // 有新链接申请,即listen_sock读事件就绪 if(i == 0 && FD_ISSET(listen_sock ,&fd)) { struct sockaddr_in client; socklen_t len = sizeof(client); //将new_sock添加进数组,并且寻找最小的未被使用的空间 int new_sock = accept(listen_sock, (struct sockaddr*)&client, &len); if(new_sock < 0) { perror("accept"); continue; } printf("get a new client: %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); int j = 1; for(; j < maxsz; ++j) { if(fd_array[j] < 0) break; } //服务器载客量已满 if(j == maxsz) { printf("fd_set full!!!\n"); close(new_sock); }else //其他读事件就绪,开始读取数据(new_sock加入数组后,循环开始的地方被添加入需要监视的文件描述符集,然后在这里开始处理) { fd_array[j] = new_sock; printf("changge of fd_array: "); } } //other file_desriptor is ready else if(i!=0 && FD_ISSET(fd_array[i], &fd)) { char buf[1024]; ssize_t s = read(fd_array[i], buf, sizeof(buf)-1); if(s > 0) { buf[s] = 0; printf("client->%s\n", buf); } else if(s == 0) { printf("client is qute...\n"); close(fd_array[i]); fd_array[i] = -1; } else { printf("client is error!!!\n"); close(fd_array[i]); fd_array[i] = -1; } } }//for }//default break; } }//while return 0;}
阅读全文
1 0
- 网络服务器select
- 【网络】select服务器
- 【网络】Select服务器的实现
- C++网络编程服务器select模型(参考)
- Linux网络编程之select服务器
- 使用select.select编写聊天室服务器 《Python网络编程攻略》
- 网络编程(4)select函数实现I/O多路复用服务器
- windows网络编程之Winsock非阻塞select模式服务器
- 网络通信服务器模型epoll/poll/select详解
- Select服务器
- select服务器
- select服务器
- select服务器
- select服务器
- select服务器
- select服务器
- select服务器
- select服务器
- 新手指南:如何使用c118+osmocombb进行短信嗅探实验?
- ToLua学习笔记,创建自定义矩阵类
- CSS字体垂直、水平居中
- Shell 正则表达式
- Android模拟器Genymotion使用详解
- 网络服务器select
- Codeforces 588B Duff in Love【暴力】水题
- TinkPHP 自定义API基控制器类
- vue.js,基础用法实例
- Sublime 个人配置+Python环境
- Android 后台运行那些事
- 进程同步3 补充:数据的加锁操作
- libc++abi.dylib`__cxa_throw: 使用[AVAudioPlayer play]会产生__cxa_throw异常
- 信息安全(ssl、数字证书、数字签名、加密算法)