UNP 学习笔记4

来源:互联网 发布:mt4 画线下单源码 编辑:程序博客网 时间:2024/05/16 06:35

本篇主要介绍一些常见的IO模型:

1. 常见的阻塞IO

2.IO复用

3.异步IO


以下是以select实现的IO复用,单线程实现的对多个文件描述符的控制

首先来看看select函数的原型:

返回:可用的描述符数, 紧接着是可读集、可写集、异常处理集,最后一个参数是时间:NULL则阻塞等待、0则非阻塞立即返回。

int select(int maxfdpl, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);
接着是几个宏处理:

FD_ZERO(&set); /*将set清零使集合中不含任何fd*/FD_SET(fd, &set); /*将fd加入set集合*/FD_CLR(fd, &set); /*将fd从set集合中清除*/FD_ISSET(fd, &set); /*在调用select()函数后,用FD_ISSET来检测fd在fdset集合中的状态是否变化返回整型,当检测到fd状态发生变化时返回真,否则,返回假(0)*/

#include "unp.h"int main(int argc, char **argv) {int i, maxi, maxfd, listenfd, connfd, sockfd;int nready, client[FD_SETSIZE];ssize_t n;fd_set rset, allset;char buf[MAXLINE];struct sockaddr_in cliaddr, servaddr;listenfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (SA *)& servaddr, sizeof(servaddr));Listen(listenfd, LISTENQ);maxfd = listenfd;maxi = -1;for (i = 0; i < FD_SETSIZE; i++) client[i] = -1;FD_ZERO(&allset);FD_SET(listenfd, &allset);for ( ; ; ) {rset = allset;nready = Select(maxfd+1, &rset, NULL, NULL, NULL);if (FD_ISSET(listenfd, &rset)) {clilen = sizeof(cliaddr);connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);for (i = 0; i < FD_SETSIZE; i++) {if (client[i] < 0) {client[i] = connfd;break;}}if (i == FD_SETSIZE)err_quit("too many clients");FD_SET(connfd, &allset);if (connfd > maxfd) maxfd = connfd;if (i > maxi)maxi = i;if (--nready <= 0)continue;}for (i = 0; i <= maxi; i++) {if ( (sockfd = client[i]) < 0) confinue;if (FD_ISSET(sockfd, &rset)) {if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {Close(sockfd);FD_CLR(sockfd, &allset);client[i] = -1;} else Write(sockfd, buf, n);if (--nready <= 0) break;}}}}

客户端的string处理函数:

#include "unp.h"voidstr_cli(FILE *fp, int sockfd){int maxfdp1;fd_set rset;char sendline[MAXLINE], recvline[MAXNLINE];FD_ZERO(&rset);for( ; ; ) {FD_SET(fileno(fp), &rset);FD_SET(sockfd, &rset);maxfp1 = max(fileno(fp), sockfd) + 1;Select(maxfdp1, &rset, NULL, NULL, NULL);if (FD_ISSET(sockfd, &rset)) {if (Readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli:server terminated ");Fputs(recvline, stdout);}if (FD_ISSET(fileno(fp), &rset)) {if (Fgets(sendline, MAXLINE, fp) == NULL) return;Writen(sockfd, sendline, strlen(sendline));}}}



0 0