epoll复用

news2024/11/13 14:29:14

cli

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

// 服务器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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>

// 服务器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;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/812186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++11 标准模板(STL)(std::basic_ifstream)(一)

定义于头文件 <fstream> template< class CharT, class Traits std::char_traits<CharT> > class basic_ifstream : public std::basic_istream<CharT, Traits> 类模板 basic_ifstream 实现文件流上的高层输入操作。它将 std::basic_istream…

Flink - souce算子

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 1. 从Java的集合中读取数据 2. 从本地文件中读取数据 3. 从HDFS中读取数据 4. 从Socket中读取数据 5. 从Kafka中读取数据 6. 自定义Source 官方文档 - Flink1.13 1. 从Java的集合中读取数据 …

二叉树(C语言)

文章目录 1.树1.1概念1.2相关定义1.3 表示&#xff08;左孩子右兄弟&#xff09; 2.二叉树2.1概念2.2特殊的二叉树1. 满二叉树&#xff1a;2. 完全二叉树&#xff1a; 2.3二叉树的性质2.4练习 3.二叉树的存储结构1. 顺序存储2. 链式存储 4.完全二叉树的代码实现4.1堆的介绍1.堆…

ssm德宏贸易项目java人资企业办公jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 ssm德宏贸易项目 系统有1权限&#xff1a;管理员 二…

接口自动化测试平台

下载了大神的EasyTest项目demo修改了下<https://testerhome.com/topics/12648 原地址>。也有看另一位大神的HttpRunnerManager<https://github.com/HttpRunner/HttpRunnerManager 原地址>&#xff0c;由于水平有限&#xff0c;感觉有点复杂~~~ 【整整200集】超超超…

查询结果元数据-MetaData对象、数据库工具类的封装、通过反射实现数据查询的封装

六、查询结果元数据-MetaData对象 七、数据库工具类的封装 1、PropertieUtil类 2、DbUtil类 3、DBHepler类 查询&#xff1a; 4、TestDb测试类&#xff1a; 更新&#xff1a; 1&#xff09;插入&#xff1a; 2&#xff09;修改&#xff1a; 3&#xff09;删除&#xff1a; 查…

2024考研408-计算机网络 第二章-物理层学习笔记

文章目录 前言一、通信基础1.1、物理层基本概念1.1.1、认识物理层1.1.2、认识物理层的四种接口特性 1.2、数据通信基础知识1.2.1、典型的数据通信模型及相关术语1.2.2、数据通信相关术语1.2.3、设计数据通信系统要考虑的三个问题&#xff1a;问题1&#xff1a;采用单工通信/半双…

通讯录的实现(超详细)——C语言(进阶)

目录 一、创建联系人信息&#xff08;结构体&#xff09; 二、创建通讯录&#xff08;结构体&#xff09; 三、define定义常量 四、打印通讯录菜单 五、枚举菜单选项 六、初始化通讯录 七、实现通讯的的功能 7.1 增加加联系人 7.2 显示所有联系人的信息 ​7.3 单独查…

【自动化运维】Ansible常见模块的运用

目录 一、Ansible简介二、Ansible安装部署2.1环境准备 三、ansible 命令行模块3.1&#xff0e;command 模块3.2&#xff0e;shell 模块3.3&#xff0e;cron 模块3.4&#xff0e;user 模块3.5&#xff0e;group 模块3.6&#xff0e;copy 模块3.7&#xff0e;file 模块8&#xff…

C++之观察者模式(发布-订阅)

目录 模式简介 介绍 优点 缺点 代码实现 场景说明 实现代码 运行结果 模式简介 观察者模式&#xff08;Observer Pattern&#xff09;&#xff0c;也叫我们熟知的发布-订阅模式。 它是一种行为型模式。 介绍 观察者模式主要关注的是对象的一对多的关系&#xff0c; …

4-3 Working with time series

本文所用数据下载 Data from a Washington, D.C., bike-sharing system reporting the hourly count of rental bikes in 2011–2012 in the Capital Bikeshare system, along with weather and seasonal information. Our goal will be to take a flat, 2D dataset and trans…

搭建网站 --- 快速WordPress个人博客并内网穿透发布到互联网

文章目录 快速WordPress个人博客并内网穿透发布到互联网 快速WordPress个人博客并内网穿透发布到互联网 我们能够通过cpolar完整的搭建起一个属于自己的网站&#xff0c;并且通过cpolar建立的数据隧道&#xff0c;从而让我们存放在本地电脑上的网站&#xff0c;能够为公众互联…

JS——输入输出语法数组的操作

JavaScript输入输出语法 目标&#xff1a;能写出常见的JavaScript输入输出语法 输出语法 语法1&#xff1a; document.write(要输出的内容)作用&#xff1a; 向body内输出内容 注意&#xff1a; 如果输出的内容写的是标签&#xff0c;也会被解析成网页元素 语法2&#xff1a…

2023大同首届信息技术产业峰会举行,共话数字经济新未来

7月28日&#xff0c;“聚势而强共领信创”2023大同首届信息技术产业峰会圆满举行。本次峰会由中共大同市委、大同市人民政府主办&#xff0c;中国高科技产业化研究会国际交流合作中心、山西省信创协会协办&#xff0c;中共大同市云冈区委、大同市云冈区人民政府、诚迈科技&…

一文深入了解Cmk

目录 一、Cmk&#xff08;设备能力指数&#xff09;介绍&#xff1a;二、Cmk&#xff08;设备能力指数&#xff09; 概念&#xff1a;三、Cmk的应用时机&#xff1a;四、Cmk前期准备和要求&#xff1a;五、Cmk测试要求&#xff1a;六、CMK计算公式&#xff1a;七、Cmk实际操作&…

机器学习的关键词和算法总结

随着全球各行业的数据治理、数字化转型智能化辅助的引入发展&#xff0c;机器学习&#xff08;包括深度学习&#xff09;在逐步深入到各行各业&#xff0c;所以&#xff0c;有必要对机器学习的常见术语&#xff0c;经典算法及应用场景进行一次总结&#xff0c;其实机器学习兴起…

Vue2 第九节 过滤器

&#xff08;1&#xff09;定义&#xff1a;对要显示的数据进行特定格式化后再显示 &#xff08;2&#xff09;语法&#xff1a; ① 注册过滤器 1&#xff09;Vue.filter(name, callback) 全局过滤器 2&#xff09; new Vue({filters:{}}) 局部过滤器 ② 使用过滤器 1&…

SQL注入漏洞及解决(PreparedStatement对象)

四、SQL注入漏洞 加个or true都能查出来&#xff0c;很危险&#xff01;&#xff01;&#xff01; 会报错&#xff0c;因为代码中也拼了个引号 我们使用#将后面的内容注释起来&#xff0c;前面还是条完整的sql&#xff0c;还是能查到 使用—注释&#xff0c;代码可能加trim()&…

编译运行miniob最小数据库系统

minibo是一个用于教学的小型数据库系统&#xff0c;麻雀虽小五脏俱全&#xff0c;该项目包含了数据库的核心内容&#xff0c;并且代码量小&#xff0c;适合新手学习&#xff0c;最近由于需要学习c/cpp&#xff0c;因此打算从这个项目入手&#xff0c;本文就介绍编译运行miniob的…

《零基础入门学习Python》第072讲:GUI的终极选择:Tkinter9

这节课我们接着来讲解 Canvas 组件&#xff0c;既然 Cnavas 是画布的意思&#xff0c;那我们能不能让这个组件来设计一个画板呢&#xff1f;像Windows 自带的画图程序&#xff0c;我们的用户可以在上面随心所欲的绘制自己想要的图画&#xff0c;大家仔细想想&#xff0c;其实画…