epoll

来源:互联网 发布:文件制作软件 编辑:程序博客网 时间:2024/06/05 17:51

http://blog.csdn.net/jnu_simba/article/details/9075719


read_write.h

ssize_t readn(int fd, void *buf, size_t count)  {  size_t nleft = count;  ssize_t nread;  char *bufp = (char *)buf;    while (nleft > 0)  {    if ((nread = read(fd, bufp, nleft)) < 0)  {    if (errno == EINTR)  continue;  return -1;  }    else if (nread == 0) //对方关闭或者已经读到eof  return count - nleft;    bufp += nread;  nleft -= nread;  }    return count;  }    ssize_t writen(int fd, const void *buf, size_t count)  {  size_t nleft = count;  ssize_t nwritten;  char *bufp = (char *)buf;    while (nleft > 0)  {    if ((nwritten = write(fd, bufp, nleft)) < 0)  {    if (errno == EINTR)  continue;  return -1;  }    else if (nwritten == 0)  continue;    bufp += nwritten;  nleft -= nwritten;  }    return count;    }                    /* recv()只能读写套接字,而不能是一般的文件描述符 */  ssize_t recv_peek(int sockfd, void *buf, size_t len)  {  while (1)  {    int ret = recv(sockfd, buf, len, MSG_PEEK); // 设置标志位后读取后不清除缓冲区  if (ret == -1 && errno == EINTR)  continue;  return ret;  }  }                    /* 读到'\n'就返回,加上'\n' 一行最多为maxline个字符 */  ssize_t readline(int sockfd, void *buf, size_t maxline)  {  int ret;  int nread;  char *bufp = (char*)buf;  int nleft = maxline;  int count = 0;    while (1)  {  ret = recv_peek(sockfd, bufp, nleft);  if (ret < 0)  return ret; // 返回小于0表示失败  else if (ret == 0)  return ret; //返回0表示对方关闭连接了    nread = ret;  int i;  for (i = 0; i < nread; i++)  {  if (bufp[i] == '\n')  {  ret = readn(sockfd, bufp, i + 1);  if (ret != i + 1)  exit(EXIT_FAILURE);                    return ret + count;  }  }  if (nread > nleft)  exit(EXIT_FAILURE);  nleft -= nread;  ret = readn(sockfd, bufp, nread);  if (ret != nread)  exit(EXIT_FAILURE);    bufp += nread;  count += nread;  }    return -1;  }    


#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/epoll.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <vector>#include <algorithm>#include "read_write.h"//#include <sysutil.h>#define ERR_EXIT(m) \      do { \          perror(m); \          exit(EXIT_FAILURE); \      } while (0)      void activate_nonblock(int fd){int ret;int flags = fcntl(fd, F_GETFL);if (flags == -1)ERR_EXIT("fcntl");flags |= O_NONBLOCK;ret = fcntl(fd, F_SETFL, flags);if (ret == -1)ERR_EXIT("fcntl");}void deactivate_nonblock(int fd){int ret;int flags = fcntl(fd, F_GETFL);if (flags == -1)ERR_EXIT("fcntl");flags &= ~O_NONBLOCK;ret = fcntl(fd, F_SETFL, flags);if (ret == -1)ERR_EXIT("fcntl");}typedef std::vector<struct epoll_event> EventList;/* 相比于select与poll,epoll最大的好处是不会随着关心的fd数目的增多而降低效率 */int main(void){int count = 0;int listenfd;if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)ERR_EXIT("socket");struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(1234);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);int on = 1;if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)ERR_EXIT("setsockopt");if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)ERR_EXIT("bind");if (listen(listenfd, SOMAXCONN) < 0)ERR_EXIT("listen");std::vector<int> clients;int epollfd;epollfd = epoll_create1(EPOLL_CLOEXEC); //epoll实例句柄struct epoll_event event;event.data.fd = listenfd;event.events = EPOLLIN | EPOLLET; //边沿触发epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event);EventList events(16);struct sockaddr_in peeraddr;socklen_t peerlen;int conn;int i;int nready;while (1){nready = epoll_wait(epollfd, & *events.begin(), static_cast<int>(events.size()), -1);if (nready == -1){if (errno == EINTR)continue;ERR_EXIT("epoll_wait");}if (nready == 0)continue;if ((size_t)nready == events.size())events.resize(events.size() * 2);for (i = 0; i < nready; i++){if (events[i].data.fd == listenfd){peerlen = sizeof(peeraddr);conn = accept(listenfd, (struct sockaddr *)&peeraddr, &peerlen);if (conn == -1)ERR_EXIT("accept");printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));printf("count = %d\n", ++count);clients.push_back(conn);activate_nonblock(conn);event.data.fd = conn;event.events = EPOLLIN | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_ADD, conn, &event);}else if (events[i].events & EPOLLIN){conn = events[i].data.fd;if (conn < 0)continue;char recvbuf[1024] = {0};int ret = readline(conn, recvbuf, 1024);if (ret == -1)ERR_EXIT("readline");if (ret == 0){printf("client close\n");close(conn);event = events[i];epoll_ctl(epollfd, EPOLL_CTL_DEL, conn, &event);clients.erase(std::remove(clients.begin(), clients.end(), conn), clients.end());}fputs(recvbuf, stdout);writen(conn, recvbuf, strlen(recvbuf));}}}return 0;}



#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<unistd.h>#include<stdlib.h>#include<errno.h>#include<arpa/inet.h>#include<netinet/in.h>#include<string.h>#define ERR_EXIT(m) \    do { \        perror(m); \        exit(EXIT_FAILURE); \    } while (0)int main(void){int sock;if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)    //  listenfd = socket(AF_INET, SOCK_STREAM, 0)ERR_EXIT("socket error");struct sockaddr_in servaddr;memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(1234);servaddr.sin_addr.s_addr = inet_addr("192.168.1.253");/* inet_aton("127.0.0.1", &servaddr.sin_addr); */if (connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)ERR_EXIT("connect error");char sendbuf[1024] = {0};char recvbuf[1024] = {0};while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){write(sock, sendbuf, strlen(sendbuf));read(sock, recvbuf, sizeof(recvbuf));fputs(recvbuf, stdout);memset(sendbuf, 0, sizeof(sendbuf));memset(recvbuf, 0, sizeof(recvbuf));}close(sock);return 0;}


0 0
原创粉丝点击