epoll复用

cli

#include 
#include 
#include 
#include 
#include 
#include 

// 服务器ip
#define IP "192.168.250.100"
// 服务器端口
#define PORT 8888

int main()
{
  // 创建一个TCP套接字
  int cfd = socket(AF_INET, SOCK_STREAM, 0);

  // 设置服务器地址和端口
  struct sockaddr_in sin;              // 存储客户端信息
  sin.sin_family = AF_INET;            // 必须填充AF_INET;
  sin.sin_port = htons(PORT);          // 端口号的网络字节序 1024~49151
  sin.sin_addr.s_addr = inet_addr(IP); // ifconfig查看本机IP

  // 连接服务器
  if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) != 0)
  {
    perror("连接失败");
    exit(EXIT_FAILURE);
  }

  while (1)
  {
    // 从终端读取输入
    printf("请输入要发送的消息(输入q退出):");
    char buf[128] = "";
    fgets(buf, sizeof(buf), stdin);

    if (strcmp(buf, "q\n") == 0)
    {
      break;
    }

    // 发送消息给服务器
    send(cfd, buf, strlen(buf), 0);

    // 接收服务器回复的消息
    int ret = recv(cfd, buf, sizeof(buf), 0);
    if (ret > 0)
    {
      buf[ret] = '\0';
      printf("收到服务器回复:%s\n", buf);
    }
    else
    {
      perror("接收失败");
      exit(0);
    }
  }

  // 关闭套接字
  close(cfd);

  return 0;
}

ser

#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 服务器ip
#define IP "192.168.250.100"
// 服务器端口
#define PORT 8888

int main()
{

  // 创建一个TCP套接字
  int sfd = socket(AF_INET, SOCK_STREAM, 0);

  // 设置服务器地址和端口
  struct sockaddr_in sin;

  sin.sin_family = AF_INET;            // 必须填充AF_INET;
  sin.sin_port = htons(PORT);          // 端口号的网络字节序 1024~49151
  sin.sin_addr.s_addr = inet_addr(IP); // ifconfig查看本机IP

  // 将IP地址和端口号绑定到指定的套接字文件描述符上
  bind(sfd, (struct sockaddr *)&sin, sizeof(sin));

  // 监听连接
  listen(sfd, 128);

  // IO多路复用
  int fd, epfd;
  struct epoll_event event;
  struct epoll_event events[10]; // 存放就绪事件描述符的数组
  char buf[128] = {0};

  // 创建一个epoll实例
  int epoll_fd = epoll_create(1);

  // 添加服务器套接字到epoll中,关注可读事件
  event.events = EPOLLIN;
  event.data.fd = sfd;

  if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sfd, &event) == -1)
  {
    perror("epoll注册失败");
    exit(-1);
  }

  printf("服务器已启动,等待客户端连接...\n");

  while (1)
  {
    // 等待事件发生
    int ret = epoll_wait(epoll_fd, events, 10, -1);
    if (ret == -1)
    {
      perror("epoll等待失败");
      exit(EXIT_FAILURE);
    }
    struct sockaddr_in cin; // 存储客户端信息
    for (int i = 0; i < ret; i++)
    {
      // 如果是服务器套接字上有可读事件发生,表示有新的客户端连接
      if (events[i].data.fd == sfd)
      {

        socklen_t len = sizeof(cin);
        int new_fd = accept(sfd, (struct sockaddr *)&cin, &len);

        printf("客户端已连接:%s:%d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));

        // 将客户端套接字添加到epoll中,关注可读事件
        event.events = EPOLLIN;
        event.data.fd = new_fd;
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_fd, &event) == -1)
        {
          perror("epoll注册失败");
          exit(EXIT_FAILURE);
        }
      }
      else
      {
        // 如果是客户端套接字上有可读事件发生,表示有数据到达或客户端关闭连接
        int cfd = events[i].data.fd;
        char buf[128] = "";
        // 从客户端接收数据
        int ret = recv(cfd, buf, sizeof(buf), 0);
        if (ret > 0)
        {
          printf("收到来自客户端的数据:%s\n", buf);

          // 回复客户端收到的数据
          strcat(buf, "-_- ");
          send(cfd, buf, ret + 4, 0);
        }
        else if (ret == 0)
        {
          // 客户端关闭连接
          printf("客户端已关闭:%s:%d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));

          // 从epoll中移除,并关闭套接字
          epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cfd, NULL);
          close(cfd);
        }
        else
        {
          perror("数据接收失败");
          exit(0);
        }
      }
    }
  }

  // 关闭服务器套接字
  close(sfd);

  return 0;
}

 

你可能感兴趣的:(github)