当前位置: 首页 > news >正文

网站开发技能有哪些网站建设艾金手指科杰

网站开发技能有哪些,网站建设艾金手指科杰,typecho 企业网站,做电脑系统网站转载#xff1a;http://www.jb51.net/article/101057.htm 1、基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取#xff0c;它就通知该进程。IO多路复用适用如下场合#xff1a; #xff08;1#xff09;当客户处理多个描述字时#xff08;一般…转载http://www.jb51.net/article/101057.htm 1、基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取它就通知该进程。IO多路复用适用如下场合 1当客户处理多个描述字时一般是交互式输入和网络套接口必须使用I/O复用。 2当一个客户同时处理多个套接口时而这种情况是可能的但很少出现。 3如果一个TCP服务器既要处理监听套接口又要处理已连接套接口一般也要用到I/O复用。 4如果一个服务器即要处理TCP又要处理UDP一般要使用I/O复用。 5如果一个服务器要处理多个服务或多个协议一般要使用I/O复用。 与多进程和多线程技术相比I/O多路复用技术的最大优势是系统开销小系统不必创建进程/线程也不必维护这些进程/线程从而大大减小了系统的开销。 2、select函数 该函数准许进程指示内核等待多个事件中的任何一个发送并只在有一个或多个事件发生或经历一段指定的时间后才唤醒。函数原型如下 #include sys/select.h #include sys/time.h int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout) 返回值就绪描述符的数目超时返回0出错返回-1 函数参数介绍如下 1第一个参数maxfdp1指定待测试的描述字个数它的值是待测试的最大描述字加1因此把该参数命名为maxfdp1描述字0、1、2...maxfdp1-1均将被测试。 因为文件描述符是从0开始的。 2中间的三个参数readset、writeset和exceptset指定我们要让内核测试读、写和异常条件的描述字。如果对某一个的条件不感兴趣就可以把它设为空指针。struct fd_set可以理解为一个集合这个集合中存放的是文件描述符可通过以下四个宏进行设置 void FD_ZERO(fd_set *fdset);           //清空集合 void FD_SET(int fd, fd_set *fdset);   //将一个给定的文件描述符加入集合之中 void FD_CLR(int fd, fd_set *fdset);   //将一个给定的文件描述符从集合中删除 int FD_ISSET(int fd, fd_set *fdset);   // 检查集合中指定的文件描述符是否可以读写 3timeout告知内核等待所指定描述字中的任何一个就绪可花多少时间。其timeval结构用于指定这段时间的秒数和微秒数。 ? 1 2 3 4 5 6 7 struct timeval{       long tv_sec;  //seconds       long tv_usec; //microseconds }; 这个参数有三种可能 1永远等待下去仅在有一个描述字准备好I/O时才返回。为此把该参数设置为空指针NULL。 2等待一段固定时间在有一个描述字准备好I/O时返回但是不超过由该参数所指向的timeval结构中指定的秒数和微秒数。 3根本不等待检查描述字后立即返回这称为轮询。为此该参数必须指向一个timeval结构而且其中的定时器值必须为0。 原理图 3、测试程序 写一个TCP回射程序程序的功能是客户端向服务器发送信息服务器接收并原样发送给客户端客户端显示出接收到的信息。 服务端程序如下 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 #include stdio.h #include stdlib.h #include string.h #include errno.h #include netinet/in.h #include sys/socket.h #include sys/select.h #include sys/types.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include assert.h #define IPADDR   127.0.0.1 #define PORT    8787 #define MAXLINE   1024 #define LISTENQ   5 #define SIZE    10 typedef struct server_context_st {   int cli_cnt;    /*客户端个数*/   int clifds[SIZE];  /*客户端的个数*/   fd_set allfds;   /*句柄集合*/   int maxfd;     /*句柄最大值*/ } server_context_st; static server_context_st *s_srv_ctx NULL; /*  * */ static int create_server_proc(const char* ip,int port) {   int fd;   struct sockaddr_in servaddr;   fd socket(AF_INET, SOCK_STREAM,0);   if (fd -1) {     fprintf(stderr, create socket fail,erron:%d,reason:%s\n,         errno, strerror(errno));     return -1;   }   /*一个端口释放后会等待两分钟之后才能再被使用SO_REUSEADDR是让端口释放后立即就可以被再次使用。*/   int reuse 1;   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reuse, sizeof(reuse)) -1) {     return -1;   }   bzero(servaddr,sizeof(servaddr));   servaddr.sin_family AF_INET;   inet_pton(AF_INET,ip,servaddr.sin_addr);   servaddr.sin_port htons(port);   if (bind(fd,(struct sockaddr*)servaddr,sizeof(servaddr)) -1) {     perror(bind error: );     return -1;   }   listen(fd,LISTENQ);   return fd; } static int accept_client_proc(int srvfd) {   struct sockaddr_in cliaddr;   socklen_t cliaddrlen;   cliaddrlen sizeof(cliaddr);   int clifd -1;   printf(accpet clint proc is called.\n); ACCEPT:   clifd accept(srvfd,(struct sockaddr*)cliaddr,cliaddrlen);   if (clifd -1) {     if (errno EINTR) {       goto ACCEPT;     } else {       fprintf(stderr, accept fail,error:%s\n, strerror(errno));       return -1;     }   }   fprintf(stdout, accept a new client: %s:%d\n,       inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);   //将新的连接描述符添加到数组中   int i 0;   for (i 0; i SIZE; i) {     if (s_srv_ctx-clifds[i] 0) {       s_srv_ctx-clifds[i] clifd;       s_srv_ctx-cli_cnt;       break;     }   }   if (i SIZE) {     fprintf(stderr,too many clients.\n);     return -1;   } 101 } static int handle_client_msg(int fd, char *buf) {   assert(buf);   printf(recv buf is :%s\n, buf);   write(fd, buf, strlen(buf) 1);   return 0; } static void recv_client_msg(fd_set *readfds) {   int i 0, n 0;   int clifd;   char buf[MAXLINE] {0};   for (i 0;i s_srv_ctx-cli_cnt;i) {     clifd s_srv_ctx-clifds[i];     if (clifd 0) {       continue;     }     /*判断客户端套接字是否有数据*/     if (FD_ISSET(clifd, readfds)) {       //接收客户端发送的信息       n read(clifd, buf, MAXLINE);       if (n 0) {         /*n0表示读取完成客户都关闭套接字*/         FD_CLR(clifd, s_srv_ctx-allfds);         close(clifd);         s_srv_ctx-clifds[i] -1;         continue;       }       handle_client_msg(clifd, buf);     }   } } static void handle_client_proc(int srvfd) {   int clifd -1;   int retval 0;   fd_set *readfds s_srv_ctx-allfds;   struct timeval tv;   int i 0;   while (1) {     /*每次调用select前都要重新设置文件描述符和时间因为事件发生后文件描述符和时间都被内核修改啦*/     FD_ZERO(readfds);     /*添加监听套接字*/     FD_SET(srvfd, readfds);     s_srv_ctx-maxfd srvfd;     tv.tv_sec 30;     tv.tv_usec 0;     /*添加客户端套接字*/     for (i 0; i s_srv_ctx-cli_cnt; i) {       clifd s_srv_ctx-clifds[i];       /*去除无效的客户端句柄*/       if (clifd ! -1) {         FD_SET(clifd, readfds);       }       s_srv_ctx-maxfd (clifd s_srv_ctx-maxfd ? clifd : s_srv_ctx-maxfd);     }     /*开始轮询接收处理服务端和客户端套接字*/     retval select(s_srv_ctx-maxfd 1, readfds, NULL, NULL, tv);     if (retval -1) {       fprintf(stderr, select error:%s.\n, strerror(errno));       return;     }     if (retval 0) {       fprintf(stdout, select is timeout.\n);       continue;     }     if (FD_ISSET(srvfd, readfds)) {       /*监听客户端请求*/       accept_client_proc(srvfd);     } else {       /*接受处理客户端消息*/       recv_client_msg(readfds);     }   } } static void server_uninit() {   if (s_srv_ctx) {     free(s_srv_ctx);     s_srv_ctx NULL;   } } static int server_init() {   s_srv_ctx (server_context_st *)malloc(sizeof(server_context_st));   if (s_srv_ctx NULL) {     return -1;   }   memset(s_srv_ctx, 0, sizeof(server_context_st));   int i 0;   for (;i SIZE; i) {     s_srv_ctx-clifds[i] -1;   }   return 0; } int main(int argc,char *argv[]) {   int srvfd;   /*初始化服务端context*/   if (server_init() 0) {     return -1;   }   /*创建服务,开始监听客户端请求*/   srvfd create_server_proc(IPADDR, PORT);   if (srvfd 0) {     fprintf(stderr, socket create or bind fail.\n);     goto err;   }   /*开始接收并处理客户端请求*/   handle_client_proc(srvfd);   server_uninit();   return 0; err:   server_uninit();   return -1; } 客户端程序如下 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include netinet/in.h #include sys/socket.h #include stdio.h #include string.h #include stdlib.h #include sys/select.h #include time.h #include unistd.h #include sys/types.h #include errno.h #define MAXLINE 1024 #define IPADDRESS 127.0.0.1 #define SERV_PORT 8787 #define max(a,b) (a b) ? a : b static void handle_recv_msg(int sockfd, char *buf) { printf(client recv msg is:%s\n, buf); sleep(5); write(sockfd, buf, strlen(buf) 1); } static void handle_connection(int sockfd) { char sendline[MAXLINE],recvline[MAXLINE]; int maxfdp,stdineof; fd_set readfds; int n; struct timeval tv; int retval 0; while (1) { FD_ZERO(readfds); FD_SET(sockfd,readfds); maxfdp sockfd; tv.tv_sec 5; tv.tv_usec 0; retval select(maxfdp1,readfds,NULL,NULL,tv); if (retval -1) { return ; } if (retval 0) { printf(client timeout.\n); continue; } if (FD_ISSET(sockfd, readfds)) { n read(sockfd,recvline,MAXLINE); if (n 0) { fprintf(stderr,client: server is closed.\n); close(sockfd); FD_CLR(sockfd,readfds); return; } handle_recv_msg(sockfd, recvline); } } } int main(int argc,char *argv[]) { int sockfd; struct sockaddr_in servaddr; sockfd socket(AF_INET,SOCK_STREAM,0); bzero(servaddr,sizeof(servaddr)); servaddr.sin_family AF_INET; servaddr.sin_port htons(SERV_PORT); inet_pton(AF_INET,IPADDRESS,servaddr.sin_addr); int retval 0; retval connect(sockfd,(struct sockaddr*)servaddr,sizeof(servaddr)); if (retval 0) { fprintf(stderr, connect fail,error:%s\n, strerror(errno)); return -1; } printf(client send to server .\n); write(sockfd, hello server, 32); handle_connection(sockfd); return 0; } 4、程序结果 启动服务程序执行三个个客户程序进行测试结果如下图所示 以上就是小编为大家带来的IO多路复用之select全面总结(必看篇)全部内容了希望大家多多支持脚本之家~
http://www.zqtcl.cn/news/903065/

相关文章:

  • 网站建设挂什么费用网站建设学那些课
  • 网站定位与功能分析在互联网公司做网站
  • 安阳网站建设兼职做网站推广有哪些公司
  • 网站制作的一般过程怎么用手机搭建网站
  • 备案 网站名称 怎么改深圳建网站公司
  • html 企业网站模板网站策划书免费
  • 网站建设销售ppt拖拽建站系统源码
  • 网站托管费用多少网站的开发流程
  • 周到的商城网站建设北京品牌网站
  • 网站开发费用属于什么科目网站建设考试多选题
  • c asp做网站wordpress4.5.2文章采集
  • 百度网站建设电话建立网站站建设可以吗
  • 网站后台代码在哪修改网站如何做下一页
  • 网站开发职业要求百度推广代理商与总公司的区别
  • 西安网站建设中心网页 网 址网站区别
  • 技术支持东莞网站建设机械seo岗位是什么意思
  • 做商城网站需要备案什么域名硬件开发工具有哪些
  • 网络网站制作技巧wordpress全文
  • 韩国原生ip站群服务器左右悬停代码网站
  • 专门做广东11选5的网站网站 备案 营业执照
  • 免费扑克网站wordpress弹出服务协议窗口
  • 网站的反爬一般怎样做网站右键屏蔽
  • 茂名做网站dyiee青岛宣传片制作公司
  • 凡科网可以自己做网站吗编程常用网站
  • 做网站练手项目公司营业执照可以做几个网站
  • 聚通达网站建设网站并发要求
  • 网站建设预算申请如何写服装店网页设计素材
  • 做网站设计的公司柳州芜湖又出现一例
  • 重庆网站网站建设东莞市网站建设公司哪家好
  • php做网站如何架构wordpress 排版