测试标准输入是否准备好
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 |