select服务器的实现
来源:互联网 发布:java float和Float 编辑:程序博客网 时间:2024/06/05 10:21
select函数是来实现多路I/O复用输入/输出模型。比纯粹的阻塞I / O模型更具有实用性,因为程序句柄会停在select这里等待,直到被监视的文件句柄至少有一个发生了状态改变。
select函数的功能和调用顺序
使用select函数时可以将多个文件描述符集中到一起统一监视,项目如下:
1、是否存在套接字接受数据?2、无需阻塞传输数据的套接字有那些?3、那些套接字发生了异常?
select的函数调用方法和顺序如下:
测试代码
server:
// I/O多路转接之select实现#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<string.h>#include<stdlib.h>#include<fcntl.h>#include<sys/select.h>#define SIZE sizeof(fd_set)*8 //定义fds大小int fds[SIZE]; int startup(const char *ip,int port){ int sock = socket(AF_INET,SOCK_STREAM,0); //调用socket创建监听socket if(sock<0) { perror("socket"); exit(2); } struct sockaddr_in local; //本地地址信息结构体 local.sin_family = AF_INET; //使用IPV4进行通信 local.sin_port = htons(port);//获取端口 local.sin_addr.s_addr = inet_addr(ip);//获取ip地址 if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) {//调用bind绑定地址 perror("bind"); exit(3); } if(listen(sock,10)<0) { //调用listen开始监听 10代表listen队列中等待的连接数 perror("listen"); exit(4); } return sock;}static void usage (const char* proc){ printf("Usage:%s[local_ip] [local_port]\n",proc);}int main(int argc,char* argv[]){ if(argc!=3) { usage(argv[0]); return 1; } int listen_sock = startup(argv[1],atoi(argv[2])); int nums = sizeof(fds)/sizeof(fds[0]); int i=0; for(;i<nums;i++) { fds[i]=-1; } fds[0]=listen_sock; while(1) { int max_fd=-1; FD_ZERO(&rfds);//清空 fd_set rfds; for(i=0;i<nums;i++) { if(fds[i]>0) { FD_SET(fds[i],&rfds); if(max_fd<fds[i]) { max_fd = fds[i]; } } } struct timeval timeout = {1,0}; //设置为{0,0} 非阻塞状态 switch(select(max_fd+1,&rfds,NULL,NULL,&timeout))// 调用select函数 { case 0: printf("timeout...\n"); break; case -1: perror("select"); break; default: { //at least one fd ready! for(i=0;i<nums;i++) { if(fds[i]==-1){ continue; } if(i==0&&FD_ISSET(listen_sock,&rfds)) //检测是否有新的请求 {//listen_sock struct sockaddr_in client; socklen_t len = sizeof(client); //调用accept,返回服务器与客户端连接的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<nums;j++) { if(fds[j]==-1) { break; } } if(j==nums) { printf("client is full\n"); close(new_sock); continue; }else { fds[j]=new_sock; } }else if(i!=0&&FD_ISSET(fds[i],&rfds)) {//nomal fd ready! char buf[1024]; ssize_t s = read(fds[i],buf,sizeof(buf)-1); if(s>0) { buf[s]=0; printf("client# %s\n",buf); }else if (s==0) { close(fds[i]); fds[i]=-1; printf("client is quit!\n"); }else{ perror("read"); close(fds[i]); fds[i]=-1; } }else { } } } break; } } return 0;}
client:
#include <stdio.h>#include <sys/types.h> #include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, const char *argv[]){ int sockfd; struct sockaddr_in server_addr; char buf[100] = {0}; int n = 0; int len = sizeof(struct sockaddr_in); if(argc != 3) // ./a.out ip port { fprintf(stderr,"Usage : %s ip port!\n",argv[0]); return -1; } //1.创建用于通信的文件描述符 sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd < 0) { perror("Fail to socket"); return -1; } //2.填充服务器ip和port server_addr.sin_family = AF_INET; server_addr.sin_port = htons(atoi(argv[2])); //port server_addr.sin_addr.s_addr = inet_addr(argv[1]); //ip //3.向服务器发起连接请求 if(connect(sockfd,(struct sockaddr *)&server_addr,len) < 0) { perror("Fail to connect"); return -1; } //4.发送消息 while(1) { bzero(buf,sizeof(buf)); putchar('>'); fgets(buf,sizeof(buf),stdin); buf[strlen(buf) - 1] = '\0'; //'\n'--->'\0' n = send(sockfd,buf,strlen(buf),0); if(n < 0) { printf("Fail to send"); return -1; } if(strncmp(buf,"quit",4) == 0) break; printf("send %d bytes : %s\n",n,buf); } return 0;}
测试结果
select服务器优缺点
优点
(1)select()的可移植性更好;
(2)select()对于超时值提供了更好的精度。
(3)不需要建立多个线程、进程就可以实现一对多的通信。
(4)可以同时等待多个文件描述符,效率比起多进程多线程来说要高很多。
缺点
(1)每次调用选择,都需要把FD集合从用户态拷贝到内核态,这个开销在FD很多时会很大 ;
(2)同时每次调用选择都需要在内核遍历传递进来的所有的FD,这个开销在FD很多时也很大 ;
(3)select支持的文件描述符数量有上限,默认是1024。
阅读全文
0 0
- select服务器的实现
- select服务器的实现
- 服务器Select模型的实现
- select 实现的 socket服务器
- 【网络】Select服务器的实现
- Select实现并发服务器
- select服务器简单实现
- select实现并发服务器
- Select服务器代码实现
- 模拟实现select服务器
- select 实现 tcp echo 服务器
- Linux下select函数实现的聊天服务器
- Linux下select函数实现的聊天服务器
- Linux下select函数实现的聊天服务器
- select实现tcp并发服务器的基本框架流程
- Linux下select函数实现的聊天服务器
- 使用select系统调用实现简单的TCP服务器
- select()函数(I/O多路复用)-并发服务器的实现
- 排序算法系类-交换之冒泡优化
- Hi3519-pinctrl驱动开发③consumer driver与pinctrl子系统交互
- 226. Invert Binary Tree
- 学习笔记整理1——零碎小知识点
- 静态变量Static
- select服务器的实现
- 使用python的hdfs包操作分布式文件系统(HDFS)
- leejianjun的博客 PHP生成word并可下载
- missing: vtable for __cxxabiv1::__si_class_type_info
- c51上跑smallrtos 之4x4 矩阵键盘任务
- python 数据处理第一章 numpy库的基本用法
- X11/Xlib.h: No such file or directory X11/xpm.h: No such file or directory
- SharedPreferences详解
- JavaScript基本概念