首页 > 其他分享 >基于select进行并发处理

基于select进行并发处理

时间:2023-11-07 22:22:05浏览次数:34  
标签:lfd 基于 int rdset 并发 描述符 FD 监听 select

目录

处理流程

  1. 创建监听的套接字 lfd = socket();
  2. 将监听的套接字和本地的IP和端口绑定 bind()
  3. 给监听的套接字设置监听 listen()
  4. 创建一个文件描述符集合 fd_set,用于存储需要检测读事件的所有的文件描述符
  • 通过 FD_ZERO() 初始化
  • 通过 FD_SET() 将监听的文件描述符放入检测的集合中
  1. 循环调用select(),周期性的对所有的文件描述符进行检测
  2. select() 解除阻塞返回,得到内核传出的满足条件的就绪的文件描述符集合
  • 通过FD_ISSET() 判断集合中的标志位是否为 1
    • 如果这个文件描述符是监听的文件描述符,调用 accept() 和客户端建立连接
      • 将得到的新的通信的文件描述符,通过FD_SET() 放入到检测集合中
    • 如果这个文件描述符是通信的文件描述符,调用通信函数和客户端通信
      • 如果客户端和服务器断开了连接,使用FD_CLR()将这个文件描述符从检测集合中删除
      • 如果没有断开连接,正常通信即可

服务端代码

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

int main()
{
    printf("%s 向你问好!\n", "IOSelect");
    //监听的fd
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if (lfd == -1)
    {
        perror("socket");
        return -1;
    }
    //绑定端口
    sockaddr_in serveraddr;
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(9999);
    int ret=bind(lfd, (sockaddr*)&serveraddr, sizeof(sockaddr_in));
    if (ret == -1)
    {
        perror("bind");
        return -1;
    }

    //设置监听
    ret = listen(lfd, 128);
    if (ret == -1)
    {
        perror("listen");
        return -1;
    }
    //rdset为所有的描述符
    fd_set rdset;
    FD_ZERO(&rdset);
    FD_SET(lfd, &rdset);
    int maxfd = lfd;
    //原始集合rdset因为tmp在select之后可能会被修改
    //tmp是传出传入的
    fd_set tmp ;


    while (1)
    {
        tmp = rdset;
        int num = select(maxfd + 1, &tmp, NULL, NULL, NULL);
        if (FD_ISSET(lfd, &tmp))
        {
            // 此时说明lfd的读缓冲区是有东西的
            sockaddr_in cliaddr;
            int cliLen = sizeof(cliaddr);
            int cfd = accept(lfd,(sockaddr* ) & cliaddr, (socklen_t*)cliLen);
            FD_SET(cfd, &rdset);
            maxfd = cfd>maxfd?cfd:maxfd;
        }
        for (int i = 0; i <= maxfd; i++)
        {
            if (i != lfd && FD_ISSET(i, &tmp))
            {
                //接收数据
                char buf[10] = { 0 };
                // 一次只能接收10个字节, 客户端一次发送100个字节
                // 一次是接收不完的, 文件描述符对应的读缓冲区中还有数据
                // 下一轮select检测的时候, 内核还会标记这个文件描述符缓冲区有数据 -> 再读一次
                // 	循环会一直持续, 知道缓冲区数据被读完位置
                int len = read(i, buf, sizeof(buf));
                if (len == 0)
                {
                    printf("客户端关闭了连接...\n");
                    // 将检测的文件描述符从读集合中删除
                    FD_CLR(i, &rdset);
                    close(i);
                }
                else if (len > 0)
                {
                    // 收到了数据
                    // 发送数据
                    write(i, buf, strlen(buf) + 1);
                }
                else
                {
                    // 异常
                    perror("read");
                }
            }
        }
    }


    return 0;
}

标签:lfd,基于,int,rdset,并发,描述符,FD,监听,select
From: https://www.cnblogs.com/liviayu/p/17816193.html

相关文章

  • 让自定义的容器,也能基于范围循环
      C++11起,引入了基于范围的for循环这一特性,有什么好处呢?它有时可以大大地简化遍历容器的操作,比如说STL的vector。std::vectorv{1,2,3};std::vector<int>::iteratorit=begin(v);for(;it!=end(v);++it)std::cout<<*it<<'\n';  这是使用了迭代器的写法,......
  • 基于springboot+vue开发的教师工作量管理系
    教师工作量管理系springboot31摘要随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足,创建了一个计算机管理教师工作量管理系统的方案。文章介绍了教师工作量......
  • Pytorch环境配置(基于pycharm集成开发环境)
    pycharm可以在官网(https://www.jetbrains.com/pycharm/)直接下载,有两个版本,社区版免费,足够深度学习使用。专业版收费,但可以使用学生邮箱注册然后免费使用。1.下载、安装anaconda到以下镜像下载对应版本的anaconda:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/note:这个版......
  • 11月7日form表单与input框以及select标签
    目录form表单与input框form表单input标签input其它属性说明:form与其它标签以及input的应用再来展示一下禁用以及隐藏的属性select标签form表单与input框form表单功能:表单用于向服务器传输数据,从而实现用户与web服务器的交互表单能够包含input系列标签,比如文本字段、复选框、......
  • HDFS基于Ranger鉴权原理
    1.背景在HDFS中,默认是通过setacl和getacl命令的方式增加和查询hdfs的acl信息。为了了解acl信息,需要亲自登陆机器执行hdfs命令,对于没有机器权限的业务人员非常不友好;同时,运维人员无法浏览HDFS所有acl信息,对于管理来说也不透明。为了解决该问题,引入了Ranger组件,将acl信息存放到Ran......
  • springboot项目基于pom.xml中的maven实现多环境配置
    在SpringBoot项目中,我们可以通过在pom.xml中配置Maven插件,结合Spring的Profile实现多环境配置。下面是一种可能的实现方式:首先,在pom.xml中添加Maven插件,该插件可以用于编译、测试和打包项目。为了能够支持多环境配置,我们可以在profiles标签内定义不同的profile,然后在build标签内的......
  • Gin+Vue+微服务打造秒杀商城,打造高并发抢购平台
    gin+vue实战后端:用户管理用户列表登录/登出商品管理商品的增上改查活动管理商品关联成功率redis队列,不成功的回到队列继续,成功的从队列删除结束难点:代码和部署完全隔离怎么避免雪崩根据后端承载能力,进行限流和过载保护使用redis承载海量QPSmysql性......
  • 数据库系列:InnoDB下实现高并发控制
    数据库系列:MySQL慢查询分析和性能优化数据库系列:MySQL索引优化总结(综合版)数据库系列:高并发下的数据字段变更数据库系列:覆盖索引和规避回表数据库系列:数据库高可用及无损扩容数据库系列:使用高区分度索引列提升性能数据库系列:前缀索引和索引长度的取舍数据库系列:MySQL引擎My......
  • vue 大文件分片上传(断点续传、并发上传、秒传)
    对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传,从上传的效率来看,利用多线程并发上传能够达到最大效率。本文是基于springboot+vue实现的文件上传,本文主要介绍vue实现文件上传的步骤......
  • 基于knn的图片识别
    基于KNN的图片识别KNN算法介绍https://zhuanlan.zhihu.com/p/25994179项目简介使用numpy和opencv实现的一个简易的knn图片识别模块项目结构-code:存放代码-create_collection.py:创建数据集功能,会将img中的图片建立数据集到data_collection下-knn.py:knn实现......