设为首页 加入收藏

TOP

IO多路复用(二) -- select、poll、epoll实现TCP反射程序(五)
2019-09-02 23:06:59 】 浏览:54
Tags:复用 select poll epoll 实现 TCP 反射 程序
测试标准输入是否准备好 if (this->clientfds[1].revents & POLLIN) { n = read(STDIN_FILENO, sendline, MAXLINE); if (n <= 0) { shutdown(this->listenfd, SHUT_WR); continue; } write(this->listenfd, sendline, n); } } } bool MyPoll::accept_client_proc() { struct sockaddr_in cliaddr; socklen_t cliaddrlen; cliaddrlen = sizeof(cliaddr); int connfd; //接受新的连接 if ((connfd = accept(this->listenfd, (struct sockaddr*)&cliaddr, &cliaddrlen)) == -1) { if (errno == EINTR) return false; else { perror("accept error:"); exit(1); } } fprintf(stdout, "accept a new client: %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); return add_event(connfd, POLLIN); //添加新的描述符 } bool MyPoll::add_event(int connfd, int event) { //将新的连接描述符添加到数组中 int i; for (i = 0; i < io_max; i++) { if (this->clientfds[i].fd < 0) { this->clientfds[i].fd = connfd; break; } } if (i == io_max) { fprintf(stderr, "too many clients.\n"); return false; } //将新的描述符添加到读描述符集合中 this->clientfds[i].events = event; if (i > this->max_index) this->max_index = i; return true; } void MyPoll::handle_client_msg() { int i, n; char buf[MAXLINE]; memset(buf, 0, MAXLINE); //处理信息 for (i = 1; i <= this->max_index; i++) { if (this->clientfds[i].fd < 0) continue; //测试客户描述符是否准备好 if (this->clientfds[i].revents & POLLIN) { //接收客户端发送的信息 n = read(this->clientfds[i].fd, buf, MAXLINE); if (n <= 0) { close(this->clientfds[i].fd); this->clientfds[i].fd = -1; continue; } write(STDOUT_FILENO, buf, n); //向客户端发送buf write(this->clientfds[i].fd, buf, n); } } } int MyPoll::wait_event() { /*开始轮询接收处理服务端和客户端套接字*/ int nready = nready = poll(this->clientfds, this->max_index + 1, INFTIM); if (nready == -1) { fprintf(stderr, "poll error:%s.\n", strerror(errno)); } if (nready == 0) { fprintf(stdout, "poll is timeout.\n"); } return nready; } //------------------------epoll--------------------------- MyEpoll::MyEpoll(int max, int listenfd) : Multiplexing(max, listenfd) { this->events = new Epoll_event[this->io_max]; //创建一个描述符 this->epollfd = epoll_create(this->io_max); } void MyEpoll::server_do_multiplexing() { int i, fd; int nready; char buf[MAXLINE]; memset(buf, 0, MAXLINE); //添加监听描述符事件 if (!add_event(this->listenfd, EPOLLIN)) { perror("add event error!"); exit(1); } while (1) { //获取已经准备好的描述符事件 nready = wait_event(); this->nready = nready; if (-1 == nready) return; if (0 == nready) continue; //进行遍历 /**这里和poll、select都不同,因为并不能直接判断监听的事件是否产生, 所以需要一个for循环遍历,这个for循环+判断类似于poll中 if (FD_ISSET(this->listenfd, this->allfds))、 select中的if (this->clientfds[0].revents & POLLIN) 这里只是尽量写的跟poll、select中的结构类似, 但是实际代码中,不应该这么写,这么写多加了一个for循环**/ for (i = 0; i < nready; i++) { fd = events[i].data.fd; //根据描述符的类型和事件类型进行处理 if ((fd == this->listenfd) && (events[i].events & EPOLLIN)) { //监听事件 /*监听客户端请求*/ if (!accept_client_proc()) //处理连接请求 continue; //说明此时产生的事件个数小于等于1,所以不必再处理下面的客户连接信息 if (--nready <= 0) continue; } } //处理客户端事件 handle_client_msg(); } close(epollfd); } bool MyEpoll::accept_client_proc() { struct sockaddr_in cliaddr; socklen_t cliaddrlen; cliaddrlen = sizeof(cliaddr); int con
首页 上一页 2 3 4 5 6 下一页 尾页 5/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇linux批量检测服务器能否ping通和.. 下一篇操作系统:进程的概念和与程序的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目