精华内容
下载资源
问答
  • 2022-01-02 22:38:30

    多路复用归功于, HTTP/2 中的 帧(frame)和流(stream)。帧代表着最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。就是在一个 TCP 连接中可以存在多条流。

    而Http 1.x 并没有这个标识,每次请求都会建立一次HTTP连接,3次握手4次挥手

    更多相关内容
  • 关键词:非多路复用总线 多路复用总线 时序 CPLD DSP微处理器对外并行总线接口方式一般分为两种,一种为多路复用方式,数据与地址采用共用引脚,分时传输;另一种是非多路复用方式,数据与地址采用分离引脚,同时...
  • 使用select和epoll实现多路复用,并使用jmeter进行测试。压缩包包含代码和学生使用的完整实验报告
  • 引言 如果设计一种负责测量多个模拟电压(但不是所有同时测量)的系统,可以通过把测量结果多路复用为单个输出信号来简化下游电路,随后采用共享组件对原始电压电平进行串行处理和数字化。这么做的好处是信号链路...
  • 下面小编就大家带来一篇IO多路复用之epoll全面总结(必看篇)。小编觉得挺不错的。现在就分享给大家。也给大家做个参考。一起跟随小编过来看看吧
  • 引言 如果设计一种负责测量多个模拟电压(但不是所有同时测量)的系统,可以通过把测量结果多路复用为单个输出信号来简化下游电路,随后采用共享组件对原始电压电平进行串行处理和数字化。这么做的好处是信号链路...
  • 是用于RPC调用的多路复用和成帧协议。 tchannel-go是该协议的Go实现,包括客户端库。 如果您想开始编写小型Thrift和TChannel服务,请参阅。 对于一些自以为是的设置,请参阅。 概述 TChannel是一种网络协议,它...
  • 什么是IO 多路复用呢? 我一个SocketServer有500个链接连过来了,我想让500个链接都是并发的,每一个链接都需要操作IO,但是单线程下IO都是串行的,我实现多路的,看起来像是并发的效果,这就是多路复用! 概念说明...
  • 多路复用IO(IO multiplexing) 这种IO方式事件驱动IO(event driven IO)。 我们都知道,select/epoll的好处就在于单个进程process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断...
  • 多路复用器-java Multiplexer-java 是的 Java 实现, 是分布式系统的高效通信工具。 在您可以阅读有关 Multiplexer 的 C++ 和 Java 实现
  • windows下多路复用IO(select,WSAAsyncSelect,WSAEventSelect)
  • 提出了一种新颖的非多路复用总线与多路复用总线的转换接口电路。以两种总线的典型代表芯片TMS320F206与SJA1000例,分析了各自时序的特点,详细论述了两种总线之间转换的关键:读、写周期的使能...
  • 其 2:1 的输入多路复用器简化了两个视频信号的选择,而放大器的内部固定增益 2,在驱动 75W 反向终接电缆时无需外部增益设置电阻。 LT6555 同样非常适合用做前端接收器或输出电缆驱动器,这是在 UXGA LCD投影机和...
  • 如果设计一种负责测量多个模拟电压(但不是所有同时测量)的系统,可以通过把测量结果多路复用为单个输出信号来简化下游电路,随后采用共享组件对原始电压电平进行串行处理和数字化。这么做的好处是信号链路组件的...
  • 这种安全数据双端口多路复用器能够实现 1.8V 主处理器与高压和双压卡之间的连接,能以低至 1µA 的电池能耗提供无缝的双向通信。  飞兆半导体的 FSSD06 与众不同,它允许应用设备的处理器在安全数字、安全数字I/O...
  • Intersil的新型多路复用器能实现在各个增益2的放大器通道上的四路不同视频输入之间的切换 ISL59446具有集成的增益2的放大器、500MHz的带宽和±1600V/μs的压摆率,可实现高质量视频切换   Intersil(NASDAQ...
  • 什么是IO多路复用?怎么实现

    千次阅读 2021-10-17 15:56:19
    IO多路复用(IO Multiplexing)是指单个进程/线程就可以同时处理多个IO请求。 实现原理:用户将想监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符...

    IO多路复用(IO Multiplexing)是指单个进程/线程就可以同时处理多个IO请求。

    实现原理:用户将想要监视的文件描述符(File Descriptor)添加到select/poll/epoll函数中,由内核监视,函数阻塞。一旦有文件描述符就绪(读就绪或写就绪),或者超时(设置timeout),函数就会返回,然后该进程可以进行相应的读/写操作。

    select/poll/epoll三者的区别?

    • select:将文件描述符放入一个集合中,调用select时,将这个集合从用户空间拷贝到内核空间(缺点1:每次都要复制,开销大),由内核根据就绪状态修改该集合的内容。(缺点2)集合大小有限制,32位机默认是1024(64位:2048);采用水平触发机制。select函数返回后,需要通过遍历这个集合,找到就绪的文件描述符(缺点3:轮询的方式效率较低),当文件描述符的数量增加时,效率会线性下降;
    • poll:和select几乎没有区别,区别在于文件描述符的存储方式不同,poll采用链表的方式存储,没有最大存储数量的限制;
    • epoll:通过内核和用户空间共享内存,避免了不断复制的问题;支持的同时连接数上限很高(1G左右的内存支持10W左右的连接数);文件描述符就绪时,采用回调机制,避免了轮询(回调函数将就绪的描述符添加到一个链表中,执行epoll_wait时,返回这个链表);支持水平触发和边缘触发,采用边缘触发机制时,只有活跃的描述符才会触发回调函数。

    总结,区别主要在于:

    • 一个线程/进程所能打开的最大连接数
    • 文件描述符传递方式(是否复制)
    • 水平触发 or 边缘触发
    • 查询就绪的描述符时的效率(是否轮询)

    什么时候使用select/poll,什么时候使用epoll?

    当连接数较多并且有很多的不活跃连接时,epoll的效率比其它两者高很多;但是当连接数较少并且都十分活跃的情况下,由于epoll需要很多回调,因此性能可能低于其它两者。

    什么是文件描述符?

    文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。

    内核通过文件描述符来访问文件。文件描述符指向一个文件。

    什么是水平触发?什么是边缘触发?

    • 水平触发(LT,Level Trigger)模式下,只要一个文件描述符就绪,就会触发通知,如果用户程序没有一次性把数据读写完,下次还会通知;
    • 边缘触发(ET,Edge Trigger)模式下,当描述符从未就绪变为就绪时通知一次,之后不会再通知,直到再次从未就绪变为就绪(缓冲区从不可读/写变为可读/写)。
    • 区别:边缘触发效率更高,减少了被重复触发的次数,函数不会返回大量用户程序可能不需要的文件描述符。
    • 为什么边缘触发一定要用非阻塞(non-block)IO:避免由于一个描述符的阻塞读/阻塞写操作让处理其它描述符的任务出现饥饿状态。

    有哪些常见的IO模型?

    • 同步阻塞IO(Blocking IO):用户线程发起IO读/写操作之后,线程阻塞,直到可以开始处理数据;对CPU资源的利用率不够;
    • 同步非阻塞IO(Non-blocking IO):发起IO请求之后可以立即返回,如果没有就绪的数据,需要不断地发起IO请求直到数据就绪;不断重复请求消耗了大量的CPU资源;
    • IO多路复用
    • 异步IO(Asynchronous IO):用户线程发出IO请求之后,继续执行,由内核进行数据的读取并放在用户指定的缓冲区内,在IO完成之后通知用户线程直接使用。

    展开全文
  • 这种安全数据双端口多路复用器能够实现 1.8V 主处理器与高压和双压卡之间的连接,能以低至 1μA 的电池能耗提供无缝的双向通信。  飞兆半导体的 FSSD06 与众不同,它允许应用设备的处理器在安全数字、安全数字I/O...
  • 下面小编就大家带来一篇IO多路复用之poll全面总结(必看篇)。小编觉得挺不错的。现在就分享给大家。也给大家做个参考。一起跟随小编过来看看吧
  • 利用高速放大器实现低成本视频多路复用
  • 多程序传输流多路复用器的设计与实现
  • select 实现多路复用

    千次阅读 2018-07-18 21:59:58
    //TCP服务器使用select实现多路复用 //定义一个结构体来保存文件描述符集和当前关注的最大文件描述 typedef struct Fd_set { fd_set fds; int max_fd; }Fd_set; //初始化文件描述符集 void Init_...

    以下内容均为本人学习笔记,若有错误,欢迎指出

    select的使用

    在前面讲了五种基本IO模型:初识化五种IO模型

    其实我们用到的最多的就是多路IO,今天来学习了解select()实现多路IO

    先看接口如何使用

           #include <sys/time.h>
           #include <sys/types.h>
           #include <unistd.h>
    
           int select(int nfds, fd_set *readfds, fd_set *writefds,
                      fd_set *exceptfds, struct timeval *timeout);
    
    • 第一个参数 nfds 为你所要等待的文件描述符的最大值的值再 +1 ,因为这里的fd_set 文件描述符集其实是一个位图,当每次进行设置修改时都要遍历,这样给定最大范围,可以提高效率
    • 第二个参数为要等待的可读的文件描述符集
    • 第三个参数为要等待的可写的文件描述符集
    • 第四个参数为要等待的异常文件描述符集
    • 第五个参数为一个表示时间的结构体,用来设置select()的等待时间

    除了第一个参数,其他参数都是既为输入型参数又为输出型参数
    rdset、wrset、exset结构是一个整数数组,理解为一个位图:
    *作为输入型参数,用户告诉操作系统,你要等待哪些文件描述符的就绪状态
    *作为输出行参数,操作系统告诉用户哪些文件描述符状态已经就绪
    timeout结构:
    若等待时间没有超过timeout,则返回为剩余时间

    其实这里存在一个问题,我们每次非阻塞形式读取文件并不是只读一次,都是循环等待文件描述符状态,读取数据,那么上面的fd_set结构在每次返回的时候,都会更新为就绪的文件描述符集,再次等待的时候,就不能直接使用了,所以这里需要一个第三方变量保存作为输入的文件描述集。需要将输入输出参数关联性分离,其实这也是select的一个短板。

    下面的接口用来操作fd_set:

           void FD_CLR(int fd, fd_set *set);
           int  FD_ISSET(int fd, fd_set *set);
           void FD_SET(int fd, fd_set *set);
           void FD_ZERO(fd_set *set);
    

    什么是读就绪状态

    • socket内核中,接收缓冲区的中字节数大于等于低水位标记SO_RCVLOWAT(socket recevice low water mark),此时可以进行无阻塞的读取该文件描述符,并且返回值大于0。
    • socketTCP通信中对端关闭连接,此时对该文件进行读取,则返回0。
    • socket使用非阻塞connect连接成功或者失败之后。
    • socket有未读取的错误时。

    什么是写就绪状态

    • socket内核中,发送缓冲区的中可用字节数(发送缓冲区中空闲位置的大小)大于等于低水位标记SO_SNDLOWAT(socket send low water mark),此时可以进行无阻塞的对该文件进行写操作,并且返回值大于0。
    • socket的写操做被关闭,试图进行写操作时,会触发SIGPIPE信号。
    • socket使用非阻塞connect连接成功或者失败之后。
    • socket上有未读取的错误。

    使用select只检测标准输入是否就绪

    #include <stdio.h>
    #include <sys/select.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    //使用select 检测标准输入
    int main()
    {
    //1.准备好文件描述符集
      fd_set read_set;
      int fd = 0;//stdin
      FD_ZERO(&read_set);
      FD_SET(fd,&read_set);
    
      while(1)
      {
        int ret = select(fd + 1,&read_set,NULL,NULL,NULL);
        //此处只检测读就绪,写和异常不用理会,并设置为阻塞式检测
        if(ret < 0)
        {
          perror("select");
          continue;
        }
        printf("ret : %d\n",ret);
        if(FD_ISSET(fd,&read_set) == 0)
        {
          //说明出错
          printf("error!\n");
          continue;
        }
        else
        {
          char buf[1024] = {0};
          if(read(fd,buf,sizeof(buf)-1) > 0)
          {
            printf("%s\n",buf);
          }
        }
        //一次之后,重新调整read_set
        FD_ZERO(&read_set);
        FD_SET(fd,&read_set);
      }
      return 0;
    }

    之前我们实现的TCP服务器都是采用多进程或者多线程的方式,这种方式其实现实中根本用不到。
    用select 实现一个回显服务器

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <sys/select.h>
    #include <unistd.h>
    
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    
    //TCP服务器使用select实现多路复用
    
    //定义一个结构体来保存文件描述符集和当前关注的最大文件描述
    typedef struct Fd_set
    {
      fd_set fds;
      int max_fd;
    }Fd_set;
    
    //初始化文件描述符集
    void Init_set(Fd_set * Fds)
    {
      if(Fds == NULL)
        return;
      Fds->max_fd = -1;
      FD_ZERO(&Fds->fds);
    }
    //对文件描述符集进行设置新的文件描述符
    void Set_fds(int fd,Fd_set * Fds)
    {
      if(Fds == NULL)
        return;
      //更新 max_fd
      if(Fds->max_fd < fd)
      {
        Fds->max_fd = fd;
      }
      //设置fds
      FD_SET(fd,&Fds->fds);
    }
    //从文件描述符集中删除一个文件描述符
    void Delete_fds(int fd,Fd_set * Fds)
    {
      if(Fds == NULL)
        return;
      if(fd > Fds->max_fd)
        return;
      if(Fds->max_fd > fd)
      {//如果最大的文件描述符大于要删除的文件描述符
        //可以直接进行删除
        FD_CLR(fd,&Fds->fds);
      }
      else
      {//如果最大的文件描述符等于要删除的文件描述符
        //此时就要重新设最大文件描述符
        int i = 0;
        int max_fd = -1;
        FD_CLR(fd,&Fds->fds);
        //此处采用从最大的开始找的方法,虽然时间复杂度都为O(N)
        for(i = Fds->max_fd;i >= 0; --i)
        {
            if(FD_ISSET(i,&Fds->fds))
            {
              max_fd = i ;
            }
        }
        Fds->max_fd = max_fd;
      }
    }
    
    //获取listen_socket
    int server_start(char * IP,short Port)
    {
      //创建socket
      int listen_socket = socket(AF_INET,SOCK_STREAM,0);
      if(listen_socket < 0)
      {
        perror("socket");
        return -1;
      }
      //定义sockaddr_in 结构
      sockaddr_in addr;
      socklen_t addr_len = sizeof(addr);
      addr.sin_family = AF_INET;//IPV4
      addr.sin_addr.s_addr = inet_addr(IP);
      addr.sin_port = htons(Port);
    
      //绑定IP和端口号
      int ret = bind(listen_socket,(sockaddr *)&addr,addr_len);
      if(ret < 0)
      {
        perror("bind");
        return -1;
      }
      //监听socket使其处于可以被建立连接状态
      ret = listen(listen_socket,5);
      if(ret < 0)
      {
        return -1;
      }
      //将listen_socket返回
      return listen_socket;
    }
    
    int process_connection(int new_socket,sockaddr_in *peer)
    {
      //这里处理连接就只读一次,因为我们将所有的等到都交给了select 
      //这里只进行读操作和响应
      char buf[1024] = {0};
      ssize_t read_size = read(new_socket,buf,sizeof(buf) - 1);
      if(read_size < 0)
      {
        perror("read");
        return -1;
      }
      if(read_size == 0)
      {
        printf("read done\n");
        return 0;
      }
      buf[read_size] = '\0';
      printf("perr [%s:%d]  say : %s\n",inet_ntoa(peer->sin_addr),ntohs(peer->sin_port),buf);
    
      //回显服务,收到什么内容,就回复什么内容
      write(new_socket,buf,strlen(buf));
      return 1;
    }
    
    int main(int argc ,char * argv[])
    {
      //1.判断命令行参数正确性
      if(argc != 3)
      {
        printf("Usage [./server] [IP]  [Port]\n");
        return 1;
      }
    
      int listen_socket =server_start( argv[1],atoi(argv[2]));
      if(listen_socket < 0)
      {
        printf("start faile\n");
        return -1; 
      }
      printf("start ok\n");
    
      //定义文件描述符集并进行初始化和设置
      Fd_set in_put;
      Init_set(&in_put);
      Set_fds(listen_socket,&in_put);
    
      //因为这里第二个参数既是输入行参数,又是输出型参数
      //为了防止将第二次需要再次等待的文件描述符集破坏掉,需要定义一个输出参数用来保存输出文件描述符集
      Fd_set out_put = in_put;
    
      //进行事件循环
      while(1)
      {
        sockaddr_in peer;
        socklen_t peer_len = sizeof(peer);
        in_put = out_put;
        int ret = select(in_put.max_fd + 1,&in_put.fds,NULL,NULL,NULL);
        if(ret < 0)
        {
          printf("select filed\n");
          continue;
        }
        if(ret == 0)
        {
          printf("time put\n");
          continue;
        }
        //判断listen_sock是否就绪,若就绪,就可以进行accpet()
        if(FD_ISSET(listen_socket,&in_put.fds))
        {
          int new_socket = accept(listen_socket,(sockaddr *)&peer,&peer_len);
          if(new_socket < 0)
          {
            perror("accept");
            continue;
          }
          else
          {//此处建立连接成功后,应该将 new_socket设置在out_put中保存下来中
            Set_fds(new_socket,&out_put);
            printf("client %d connect!\n",new_socket);
          }
        }
        else
        {//处理已经就绪的new_sock
          int i = 0;
          for(i = 0; i < in_put.max_fd + 1; ++i)
          {
            if(FD_ISSET(i , &in_put.fds))
            {//如果这个文件描述符已经就绪,就进行处理本次连接
              //将这一位文件描述符进行设置
              Set_fds(i , &out_put);
              int ret = process_connection(i,&peer);
              if(ret <= 0)
              {//说明本次连接已经结束
                //需要将out_put里面的这个文件描述清理掉
                Delete_fds(i,&out_put);
                close(i);
                printf("%d closed \n",i);
              }
            }
            else
            {
              //如果还没有就绪
              //就检测其他的文件描述符
              continue;
            }
          }
        }
      }
    }
    
    //其实这里还存在一个问题,上面我们处理listen_socket和new_socket的处理是is-else结构的
    //但是listen_socket和new_socket是很有可能同时就绪的
    //但是这里也影响,因为这次没有处理,循环会继续执行,会在下一次循环处理
    //我们将这种处理方式称为水平触发
    

    select 的缺点:

    1.可监控的文件描述符集大小有限制,sizeof(fd_set)根据机器不同,这边的数值为128字节,说明可监控文件描述符为1024
    2. 每次调用select,都需要自己手动设置fd_set,从接口使用来说不方便,并且输入输出参数为一个值,还需要自己维护第三个变量
    3. 每次调用select 都需要将fd集从用户态拷贝到内核态,这边为128*3字节,虽然感觉上不大,但是拷贝次数太频繁
    4.每次不管是内核还是我们自己在使用的时候,都要遍历fd,开销也挺大的

    展开全文
  • 微处理器对外并行总线接口方式一般分为两种,一种为多路复用方式,数据与地址采用共用引脚,分时传输;另一种是非多路复用方式,数据与地址采用分离引脚,同时传输。目前国内应用广泛的MCS196MCS196和MCS...
  •  Libevent支持多种I/O多路复用技术的关键在于结构体eventop,它的成员是一系列的函数指针, 定义在event-internal.h文件中: struct eventop { const char *name; void *(*init)(struct ...
  • io多路复用帮助你更快更轻松的掌握多并发服务器的搭建
  • 1.控制文件的作用 2.控制文件多路复用管理的优势 3.在windows 平台下的oracle数据库中实现控制文件多路复用管理机制 4.在操作中出现的问题及解决方法 5.操作过程注意的地方
  • MAX440是MAXIM公司生产的8通道视频高速多路复用芯片,其切换时间15ns,是一种CMOS集成电路。它的管脚排列如图1所示,功能如表1所列。图2所示是MAX440的内部功能框图及外部匹配电路。它由多路开关和运算放大
  • Linux下GSM0710 CMUX源码,实现串口多路复用,linux 下交叉编译后,拷入使用环境,运行gsm0710muxd_bp -s /dev/ttyS0 -b 115200 -n 3 &,成功后可以看到 /dev/下出现 /chn文件夹,打开看到1、2、3共3个端口,3个口都...
  • GSM0710 CMUX源码,实现串口多路复用,实测可用 我用在gprs模块端口复用上,linux 下交叉编译后,拷入使用环境,运行gsm0710muxd_bp -s /dev/ttyS0 -b 115200 -n 3 &,成功后可以看到 /dev/下出现 /chn文件夹,打开...
  • IO多路复用实现TCPecho

    2014-03-02 11:46:24
    自己写的TCPecho服务器,利用IO多路复用技术,注意是linux源码,非windows

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 125,055
精华内容 50,022
关键字:

为什么要实现多路复用

友情链接: phaseshift_bf.rar