1.创建socketfd和epoll

  // 创建epollfd.
  int epfd = epoll_create(1);

 

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

2.绑定端口号

  struct sockaddr_in serveraddr;
  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  serveraddr.sin_port = htons(17099);
  // 绑定.
  if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) == -1)
  {
    perror("bind");
    exit(-1);
  }

3. 监听

  // 监听.
  if (-1 == listen(sockfd, 10))
  {
    perror("listen");
    exit(-1);
  }

4.将这个fd加入epoll(水平触发)

  // 将socketfd添加到epoll.
  struct epoll_event ep_event;
  ep_event.events = EPOLLIN;
  ep_event.data.fd = sockfd;
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ep_event) == -1)
  {
    perror("epoll_ctl");
    exit(-1);
  }

5.声明epoll_event数组,然后循环epoll_wait

  struct epoll_event events[1024] = {0};
  while (1)
  {
    int nready = epoll_wait(epfd, events, 1024, -1);

6.遍历nready,然后判断是否是服务端socket

    for (int i = 0; i < nready; i++)
    {
      struct sockaddr_in clientaddr;
      socklen_t len = sizeof(clientaddr);
      char ip[20];
      if (events[i].data.fd == sockfd)
      {

7.然后accept获取客户端socket,并添加到epoll

        int client = accept(events[i].data.fd, (struct sockaddr *)&clientaddr, &len);
        inet_ntop(AF_INET, &(clientaddr.sin_addr), ip, len);
        printf("%d connect: ip %s port %d\n", client, ip, clientaddr.sin_port);
        // 将新的fd添加到epoll
        ep_event.data.fd = client;
        epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ep_event);

8.如果epoll_wait有EPOLL_IN事件,则说明有消息,recv

      }else if(events[i].events & EPOLLIN){
        char buffer[1024] = {0};
        int count = recv(events[i].data.fd, &buffer, sizeof(buffer), 0);

9.如果这个count是-1,则说明recv错误;如果是0,则说明客户端断开;如果大于0,则说明有消息

        if (count == -1)
        {
          printf("recv error %m\n");
          continue;
        }
        else if (count == 0)
        {
          // 说明连接断开.
          printf("%d disconnect: ip %s port %d\n", events[i].data.fd, ip, clientaddr.sin_port);
          close(events[i].data.fd);
          epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
        }
        else
        {
          printf("recv: %s\n", buffer);
          send(events[i].data.fd, &buffer, count, 0);
        }