精华内容
下载资源
问答
  • 网络通信模型
    千次阅读
    2019-06-02 23:31:00

    网络通信模型

    一,起源

      由于计算机网络的飞速发展,各大产商根据自己的协议生产不同的硬件和原件,为了实现不同的网络之间的互相通信,iso和ieee相继提出了osi参考模型,和tcp、ip模型

    二,osi分层结构

    1 物理层(比特流的传输)

       物理层不是指物理设备或屋里媒体

      四个特征

          机械特性

         电器特性

         功能特性

         规程特性

      涵盖网络协议的三个要素:语法,语义,同步。

     从数据链路层向物理层传递byte流 、由物理层交换数据

    2 数据链路层(提供介质访问,链路管理等)

      主要负责数据链路的建立,维持和拆除,确保在一段物理链路上的数据帧的正确传输,建立相邻节点之间的数据传输

      四个功能

         帧同步

        差错控制

       流量控制

       链路管理

    3 网络层(寻址和路由选择)

       数据链路层是相邻两直接链接节点间的通信协议,它不能解决数据经过通信网络中多个转接节点的通讯问题

       四个功能

         编址

        路由

       拥塞控制

       异种网络互联

       主要目的:要以报文分组以最佳的路径通过网络到达目的主机而提供服务,让网络用户不必关注网络拓扑的结构与之通讯所使用的协议

      可路由协议:地给你一数据包各个字段的格式和用途,对数据包进行网络封装

      路由协议:在路由器之间传递信息,计算路由并形成路由表,为路由协议选择路径

    4 传输层 (建立主机端到端的链接)

       传输层主要利用通信子网,进行通信的来两个主机提供可靠的,透明的,端到端多路数据传输服务

      分段上层数据

      建立端到端连接

      透明可靠

      流量控制

    5 会话层 (建立维护管理会话

    6 表示层 (处理数据格式数据加密等)

    7 应用层 (提供应用程序之间的通讯)

     

      

    posted @ 2019-06-02 23:31 菜鸟的进击 阅读( ...) 评论( ...) 编辑 收藏
    更多相关内容
  • 频分复用(Frequency division multiplexing,FDM)通信模型仿真研究。FDM系统复用和解复用原理,编程实现FDM通信系统。
  • 本文突破了以往组通信模型在设计时,仅局限在网络中的某一单层上寻找解决方案的传统思想,创新性地将现有的网络层组通信模型和应用层组通信模型,按域内和域间的网络划分进行联合部署,从而提出了“域间单播+域内组...
  • c++ 网络通信模型 select模型 windows编程 网络编程
  • 图解Kafka的服务端的网络通信模型

    万次阅读 多人点赞 2022-03-25 10:25:54
    在开始讲解Kafka的网络通信模型之前,我们有必要先简单了解一下:线程模型 Reactor模式 Reactor模式 Reactor 模式,是指通过一个或多个输入同时传递给服务处理器的服务请求的事件驱动处理模式。 服务端程序处理传入多...
    🔥《Kafka运维管控平台LogiKM》🔥
    ✏️更强大的管控能力✏️
    🎾更高效的问题定位能力🎾
    🌅更便捷的集群运维能力🌅
    🎼更专业的资源治理🎼
    🌞更友好的运维生态🌞

    1. Kafka网络模型使用的是什么线程模型?
    2. 什么是ControllerPlane(控制器面板),什么是DataPlane(数据面板)?
    3. Kafka整个请求流程是什么样子的
    4. 与Kafka网络通信相关的配置。

    为更好的阅读体验,和及时的勘误
    请访问原文链接:图解Kafka服务端网络通信模型

    Kafka的网络模型

    Kafka中的网络模型就是基于 主从Reactor多线程进行设计的, 在整体讲述Kafka网络模型之前,我们现在按照源码中的相关类来讲解一下他们分别都是用来做什么的.

    关键类解析

    SocketServer

    这个类是网络通信的核心类,它持有这Acceptor和 Processor对象。

    ConnectionQuotas

    这个是控制连接数配额的类,

    涉及到的Broker配置有:

    属性描述默认
    max.connections.per.ip来自每个IP地址的最大连接数。如果达到的限制,则来自该IP地址的新链接将被丢弃。2147483647
    max.connections.per.ip.overrides针对指定IP或者主机设置最大连接数, 可以配置多个,用逗号隔开。例如:“主机名:100,127.0.0.1:200” , 这个配置会覆盖 max.connections.per.ip配置”“
    max.connectionsBroker中的最大连接数, 当然也可以配置监听器级别的限制,使用方法是在配置前面加上前缀;例如:listener.name.具体的监听器名称.max.connections=xxx 。特别需要注意的是,就算Broker已经达到了最大连接数的限制了, 也应该允许 broker之间监听器上的连接, 这种情况下,将会关闭另外一个监听器上最近最少使用的连接。broker之间的监听器是配置 inter.broker.listener.name 决定的2147483647

    AbstractServerThread

    AbstractServerThread 类:这是 Acceptor 线程和 Processor 线程的抽象基类,它定义了一个抽象方法wakeup() ,主要是用来唤醒Acceptor 线程和 Processor 对应的Selector的, 当然还有一些共用方法

    Acceptor 和 Processor

    Acceptor 线程类:继承自AbstractServerThread, 这是接收和创建外部 TCP 连接的线程。每个 SocketServer 实例一般会创建一个 Acceptor 线程(如果listeners配置了多个就会创建多个Acceptor)。它的唯一目的就是创建连接,并将接收到的 SocketChannel(SocketChannel通道用于传输数据) 传递给下游的 Processor 线程处理,Processor主要是处理连接之后的事情,例如读写I/O。

    涉及到的Broker配置有:

    属性描述默认
    listeners监听器配置,可以配置多个,配置了几个就会创建几个Acceptorlisteners = PLAINTEXT://:9092
    socket.send.buffer.bytesSocketServer的 SO_SNDBUF 缓冲区。如果值为 -1,将使用操作系统默认值。102400(100 kibibytes)
    socket.receive.buffer.bytesSocketServer sockets 的SO_RCVBUF 缓冲区,如果值为 -1,将使用操作系统默认值102400 (100 kibibytes)
    num.network.threads单个Acceptor创建Processor处理器的线程个数3

    Processor 线程类:这是处理单个 TCP 连接上所有请求的处理线程。每个 Acceptor 实例创建若干个(num.network.threads)Processor 线程。Processor 线程负责将接收到的 SocketChannel(SocketChannel通道用于传输数据。), 注册读写事件,当数据传送过来的时候,会立即读取Request数据,通过解析之后, 然后将其添加到 RequestChannel 的 requestQueue 队列上,同时还负责将 Response 返还给 Request 发送方。

    涉及到的Broker配置有:

    属性描述默认
    socket.request.max.bytesSocket请求中的最大字节数。104857600(100 mebibytes)
    connections.max.idle.msprocessor线程关闭空闲时间超过此值的连接600000 (10 minutes)
    connection.failed.authentication.delay.ms这是身份验证失败时连接关闭延迟的时间(以毫秒为单位)。这必须配置为小于 connections.max.idle.ms 以防止连接超时。100

    简单画了一张两个类之间的关系图

    在这里插入图片描述

    1. 这两个类都是 AbstractServerThead的实现类,超类是Runnable 可运行的。
    2. 每个Acceptor持有num.network.threadsProcessor 线程, 假如配置了多个listeners,那么总共Processor线程数是 listeners*num.network.threads.
    3. Acceptor 创建的是ServerSocketChannel通道,这个通道是用来监听新进来的TCP链接的通道,通过serverSocketChannel.accept()方法可以拿到SocketChannel通道用于传输数据。
    4. 每个Processor 线程都有一个唯一的id,并且通过Acceptor拿到的SocketChannel会被暂时放入到newConnections队列中
    5. 每个Processor 都创建了自己的Selector
    6. Processor会不断的从自身的newConnections队列里面获取新SocketChannel,并注册读写事件,如果有数据传输过来,则会读取数据,并解析成Request请求。

    既然两个都是可执行线程,那我们看看两个线程的run方法都做了哪些事情

    Acceptor.run

    def run(): Unit = {
        //将serverChannel 注册到nioSelector上,并且对 Accept事件感兴趣:表示服务器监听到了客户连接,那么服务器可以接收这个连接了
        serverChannel.register(nioSelector, SelectionKey.OP_ACCEPT)
        try {
          var currentProcessorIndex = 0
          while (isRunning) {
            try {
              //返回感兴趣的事件数量  这里是感兴趣的是SelectionKey.OP_ACCEPT,监听到新的链接
              val ready = nioSelector.select(500)
              if (ready > 0) {
                //获取所有就绪通道
                val keys = nioSelector.selectedKeys()
                val iter = keys.iterator()
                //遍历所有就绪通道
                while (iter.hasNext && isRunning) {
                  try {
                    val key = iter.next
                    iter.remove()
                    //只处理   Accept事件,其他的事件则抛出异常,ServerSocketChannel是 监听Tcp的链接通道
                    if (key.isAcceptable) {
                      //根据Key 拿到SocketChannle = serverSocketChannel.accept(),然后再遍历
                      accept(key).foreach { socketChannel =>
                        
                        //将socketChannel分配给我们的 processor来处理,如果有多个socketChannel 则按照轮训分配的原则
                        //如果一个processor 中能够处理的newconnection 队列满了放不下了,则找下一个
                        // 如果所有的都放不下,则会一直循环直到有processor能够处理。
    
                        var retriesLeft = synchronized(processors.length)
                        var processor: Processor = null
                        do {
                          retriesLeft -= 1
                          //轮训每个processors来处理
                          processor = synchronized {
                            // adjust the index (if necessary) and retrieve the processor atomically for
                            // correct behaviour in case the number of processors is reduced dynamically
                            currentProcessorIndex = currentProcessorIndex % processors.length
                            processors(currentProcessorIndex)
                          }
                          currentProcessorIndex += 1
                        } while (!assignNewConnection(socketChannel, processor, retriesLeft == 0))
                      }
                    } else
                      throw new IllegalStateException("Unrecognized key state for acceptor thread.")
                  } catch {
                    case e: Throwable => error("Error while accepting connection", e)
                  }
                }
              }
            }
            catch {
              省略
            }
          }
        } finally {
         省略
        }
      }
    
    1. 将ServerSocketChannel通道注册到nioSelector 上,并关注事件SelectionKey.OP_ACCEPT

      serverChannel.register(nioSelector, SelectionKey.OP_ACCEPT)
      
    2. while循环,持续阻塞监听事件,超时时间500ms

      	// 阻塞查询Selector是否有监听到新的事件
      	val ready = nioSelector.select(500)
      	// 如果有事件,则查询具体的事件和通道
      	if(ready>0>{
      	 	//获取所有就绪事件准备处理
              val keys = nioSelector.selectedKeys()
      	}
      
    3. 遍历刚刚监听到的事件, 如果该SelectionKey不包含OP_ACCEPT(建立连接)事件,则抛出异常,通常不会出现这个异常。

      Unrecognized key state for acceptor thread
      
    4. 如果SelectionKey包含OP_ACCEPT(建立连接)事件,则可以通过这个SelectionKey拿到serverSocketChannel,通过serverSocketChannel 拿到socketChannel,并且将SocketChannel设置为非阻塞模式。

      
        val serverSocketChannel = key.channel().asInstanceOf[ServerSocketChannel]
       // 调用accept方法就可以拿到ScoketChannel了。
        val socketChannel = serverSocketChannel.accept()
         //设置为非阻塞模式 就可以在异步模式下调用connect(), read() 和write()了。
        socketChannel.configureBlocking(false)
      
      
    5. 接下来,把上面拿到的SocketChannel遍历的形式给Acceptor下面的Procesor, 让Processor来执行后面的处理。分配的体现形式是, 将拿到的SocketChannel保存在Processor中的newConnections阻塞队列中,这个newConnections上限是20,在代码里面写死了的,也就是说一个Processor同时最多只能处理20个连接, 那么所有的Processor能处理的最大连接就是Processor数量 * 20;如果你的连接请求并发度很高,可以尝试调大num.network.threads

    6. 最后,如果newConnections队列放入了一个新的SocketChannel,则会调用一下对应Processor实例的wakeup()方法。

    Procesor.run

    
      override def run(): Unit = {
        startupComplete()
        try {
          while (isRunning) {
            try {
              // setup any new connections that have been queued up
              // 将之前监听到的TCP链接(暂时保存在newConnections中) 开始注册监听OP_READ事件到每个Processor的 KSelector选择器中。
              configureNewConnections()
              // register any new responses for writing
              processNewResponses()
              //在不阻塞的情况下对每个连接执行任何 I/O 操作。这包括完成连接、完成断开连接、启动新发送或在进行中的发送或接收上取得进展。
              // 当此调用完成时,用户可以使用completedSends() 、 completedReceives() 、 connected() 、 disconnected()检查已完成的发送、接收、连接或断开连接。
              poll()
              // 把请求解析后放到 requestChannels 队列中,异步处理
              processCompletedReceives()
              //处理已经发送完成的请求
              processCompletedSends()
              processDisconnected()
              closeExcessConnections()
            } catch {
              // We catch all the throwables here to prevent the processor thread from exiting. We do this because
              // letting a processor exit might cause a bigger impact on the broker. This behavior might need to be
              // reviewed if we see an exception that needs the entire broker to stop. Usually the exceptions thrown would
              // be either associated with a specific socket channel or a bad request. These exceptions are caught and
              // processed by the individual methods above which close the failing channel and continue processing other
              // channels. So this catch block should only ever see ControlThrowables.
              case e: Throwable => processException("Processor got uncaught exception.", e)
            }
          }
        } finally {
          debug(s"Closing selector - processor $id")
          CoreUtils.swallow(closeAll(), this, Level.ERROR)
          shutdownComplete()
        }
      }
    
    
    1. configureNewConnections(): 之前Acceptor监听到的SocketChannel保存在Procesor中的newConnections阻塞队列中, 现在开始将newConnections阻塞队列一个个取出来,向Procesor的Selector注册SocketChannel通道,并且感兴趣的事件为SelectionKey.OP_READ读事件。

    2. processNewResponses() : 去Processor里面的无边界阻塞队列responseQueue里面获取RequestChannel.Response数据, 如果有数据并且需要返回Response的话, 则通过channel返回数据. 具体的Channel是根据connectionId 获取之前构建的KafkaChannel, KafkaChannel则会通过监听SelectionKey.OP_WRITE。然后调用writeTo方法。
      至于responseQueue这个队列是什么时候入队的,我们后面再分析

    3. poll(): 这个方法里面执行的就很多了, 这个方法底层调用的是selector.poll(); 将监听到的事件批量处理,它才是执行I/O请求的最终地方, 它正对每个连接执行任何的I/O操作,这包括了 完成连接、完成断开连接、启动新发送等等。
      像校验身份信息,还有handshake等等这些也都是在这里执行的。

    4. processCompletedReceives(): 处理所有completedReceives(已完成接收的请求)进行接下来的处理, 处理的方式是解析一下收到的请求,最终调用了 requestChannel.sendRequest(req). 也就是说所有的请求最终通过解析放入到了RequestChannel中的requestQueue阻塞队列中, 这个阻塞队列的大小为queued.max.requests默认500;表示的是在阻塞网络线程之前,数据平面允许的排队请求数
      PS: 这个completedReceives 是在 poll()方法中添加的元素。

    5. processCompletedSends(): 它负责处理 Response 的回调逻辑,通过遍历completedSends(已完成发送)集合 可以从inflightResponses中移除并拿到response对象,然后再调用回调逻辑。
      PS: 这个completedSends 是在 poll()方法中添加的元素。

    6. processDisconnected(): 处理断开链接的情况, connectionQuotas连接限流减掉这个链接,inflightResponses也移除对应连接。

    7. closeExcessConnections(): 关闭超限连接 ,当总连接数 >max.connections && (inter.broker.listener.name!=listener|| listeners 数量==1) 则需要关闭一些连接.
      简单来说就是:就算Broker已经达到了最大连接数的限制了, 也应该允许 broker之间监听器上的连接, 这种情况下,将会关闭另外一个监听器上最近最少使用的连接。broker之间的监听器是配置 inter.broker.listener.name 决定的
      所谓优先关闭,是指在诸多 TCP 连接中找出最近未被使用的那个。这里“未被使用”就是说,在最近一段时间内,没有任何 Request 经由这个连接被发送到 Processor 线程。

    RequestChannel

    这个类保存这所有的Processor,还有一个阻塞队列保存这待处理请求。这个队列最大长度由queued.max.requests控制,当待处理请求超过这个数值的时候网络就会阻塞
    在这里插入图片描述

    涉及到的Broker配置有:

    属性描述默认
    queued.max.requests在阻塞网络线程之前,DataPlane允许的排队请求数500

    KafkaApis

    具体Request的处理类, 所有的请求方法处理逻辑都放在这个里面。

    KafkaRequestHandlerPool

    KafkaRequestHandler的线程池,KafkaRequestHandler线程的数量由配置num.io.threads决定。

    在这里插入图片描述

    涉及到的Broker配置有:

    属性描述默认
    num.io.threads服务器用于处理请求的线程数,可能包括磁盘 I/O8

    KafkaRequestHandler

    请求处理类, 每个Handler都会去 requestChannel的requestQueue队列里面poll请求, 然后去处理,最终调用的处理方法是KafkaApis.handle()

    这几个类之间的关系如下

    在这里插入图片描述

    通信流程总结

    在这里插入图片描述

    1. KafkaServer启动的时候,会根据listeners的配置来初始化对应的实例。
    2. 一个listeners对应一个Acceptor,一个Acceptor持有若干个(num.network.threads)Processor实例。
    3. Acceptor 中的nioSelector注册的是ServerSocketChannel通道,并监听OP_ACCEPT事件,它只负责 TCP 创建和连接,不包含读写数据。
    4. 当Acceptor监听到新的连接之后,就会通过调用socketChannel = serverSocketChannel.accept()拿到SocketChannel,然后把SocketChannel保存在Processor里面的newConnection队列中。 那么具体保存在哪个Processor中呢?当然是轮询分配了,确保负载均衡嘛。当然每个Processor的newConnection队列最大只有20,并且是代码写死的。如果一个Processor满了,则会寻找下一个存放,如果所有的都满了,那么就会阻塞。一个Acceptor的所有Processor最大能够并发处理的请求是 20 * num.network.threads
    5. Processor会持续的从自己的newConnection中poll数据,拿到SocketChannel之后,就把它注册到自己的Selector中,并且监听事件 OP_READ。 如果newConnection是空的话,poll的超时时间是 300ms。
    6. 监听到有新的事件,比较READ,则会读取数据,并且解析成Request, 把Request放入到 RequestChannel中的requestQueue阻塞队列中。所有的待处理请求都是临时放在这里面。这个队列也有最大值queued.max.requests(默认500),超过这个大小就会阻塞。
    7. KafkaRequestHandlerPool中创建了很多(num.io.threads(默认8))的KafkaRequestHandler,用来处理Request, 他们都会一直从RequestChannel中的requestQueue队列中poll新的Request,来进行处理。
    8. 处理Request的具体逻辑是KafkaApis里面。当Request处理完毕之后,会调用requestChannel.sendResponse()返回Response。
    9. 当然,请求Request和返回Response必须是一一对应的, 你这个请求是哪个Processor监听到的,则需要哪个Processor返回, 他们通过id来标识。
    10. Response也不是里面返回的,而是先放到Processor中的ResponseQueue队列中,然后慢慢返回给客户端。

    数据面板(DataPlane)

    数据面板是用来处理 Broker与Broker/Client之间的网络模型模块, 与之相对的是控制器面板

    控制器面板 是专门用于Controller与Broker之间的网络通信模块。

    其实本质上他们都是一模一样的, 但是为了将Controller的通信和普通通信隔离,才有这么两个概念。

    上面的网络通信模型就是以数据面板来分析的,因为本质是一样的, 只是有一些配置不一样。

    那么.数据面板 就不详细讲了,我们主要讲下控制器面板的不一样的地方

    控制器面板(ControllerPlane)

    控制器面板是用来专门处理 Controller相关请求的独立通信模块。

    大家都知道,Controller是一个很重要的角色,基本上大部分协调整个集群的相关请求都跟它有关系, 比如创建Topic、删除Topic、分区副本重分配、等等。他们都很重要

    但是一般情况下数据面板的请求很多,如果因为请求过多而导致Controller相关请求被阻塞不能执行,那么可能会造成一些影响, 所以我们可以让Controller类的请求有一个单独的通信模块。

    首先,要启用控制器面板,必须配置control.plane.listener.name. 并且这个监听器名称必须在listeners里面有配置

    否则的话,是不会专用的控制器链接的EndPoint的。

    例如:
    Broker配置

    ## 所有的监听器
    isteners = INTERNAL://192.1.1.8:9092, EXTERNAL://10.1.1.5:9093, CONTROLLER://192.1.1.8:9094
    
    ## 监听器对应的安全协议
    listener.security.protocol.map = INTERNAL: PLAINTEXT, EXTERNAL:SSL, CONTROLLER:SSL
    
    ## 控制器
    control.plane.listener.name = CONTROLLER
    

    在启动时,代理将开始使用安全协议“SSL”监听“192.1.1.8:9094”。
    在控制器端,当它通过 zookeeper 发现代理发布的端点时,它将使用 control.plane.listener.name 找到端点,它将用于建立与代理的连接。


    1. 必须配置control.plane.listener.name 才能使用独立的控制器面板
    2. 控制器面板的RequestChannel中的requestQueue不是由queued.max.requests控制的,而是写死的 20. 因为控制类请求不会有那么大的并发
    3. 跟DataPlane相关隔离,互不影响。但是连接限流ConnectionQuotas是共享的,限流的时候,两个是算在一起的
    4. 控制类面板只有一个Acceptor和一个Processor,这个跟数据面板的区别是 DataPlane的Processor可以有多个。

    涉及到的Broker配置有:

    属性描述默认
    control.plane.listener.name单独控制器面板的监听器名称,如果配置了,则Controller相关请求会有独立的专用通信模块

    上面我们主要分析了一下, Kafka中的网络通信模型, 那么聪明的你应该肯定能够看的出来,它是使用线程模型中的 Reactor模式来实现的。

    线程模型: Reactor模式

    该模块详细请参考Reactor 模型

    Reactor 模式,是指通过一个或多个输入同时传递给服务处理器的服务请求的事件驱动处理模式。
    服务端程序处理传入多路请求,并将它们同步分派给请求对应的处理线程,Reactor 模式也叫 Dispatcher 模式。
    即 I/O 多路复用统一监听事件,收到事件后分发(Dispatch 给某进程),是编写高性能网络服务器的必备技术之一。

    根据 Reactor 的数量和处理资源池线程的数量不同,有 3 种典型的实现:

    1. 单 Reactor 单线程;

    2. 单 Reactor 多线程;

    3. 主从 Reactor 多线程。

    我们主要了解一下 主从Reactor 多线程

    该图来源于网络
    针对单 Reactor 多线程模型中,Reactor 在单线程中运行,高并发场景下容易成为性能瓶颈,可以让 Reactor 在多线程中运行。

    方案说明:

    • Reactor 主线程 MainReactor 对象通过 Select 监控建立连接事件,收到事件后通过 Acceptor 接收,处理建立连接事件;

    • Acceptor 处理建立连接事件后,MainReactor 将连接分配 Reactor 子线程给 SubReactor 进行处理;

    • SubReactor 将连接加入连接队列进行监听,并创建一个 Handler 用于处理各种连接事件;

    • 当有新的事件发生时,SubReactor 会调用连接对应的 Handler 进行响应;

    • Handler 通过 Read 读取数据后,会分发给后面的 Worker 线程池进行业务处理;

    • Worker 线程池会分配独立的线程完成真正的业务处理,如何将响应结果发给 Handler 进行处理;

    • Handler 收到响应结果后通过 Send 将响应结果返回给 Client。

    更详细的介绍可以看 Reactor 模型

    问答

    1. Kafka的网络模型使用了Reactor模式的哪种实现方式?
    1. 单 Reactor 单线程;

    2. 单 Reactor 多线程;

    3. 主从 Reactor 多线程。

    答案: 3 。 使用了主从Reactor多线程的实现方式.

    在这里插入图片描述

    MainReactor(Acceptor)只负责监听OP_ACCEPT事件, 监听到之后把SocketChannel 传递给 SubReactor(Processor), 每个Processor都有自己的Selector。SubReactor会监听并处理其他的事件,并最终把具体的请求传递给KafkaRequestHandlerPool。

    很典型的主从Reactor多线程模式。

    1. 什么是ControllerPlane(控制器面板),什么是DataPlane(数据面板)?

    控制器面板: 主要处理控制器类的的请求
    数据面板: 主要处理数据类的请求。

    让他们隔离,互不影响,比如说普通的请求太多,导致了阻塞, 那么Controller相关的请求也可能被阻塞了,所以让他们隔离,不会互相影响。

    但是默认情况下, ControllerPlane是没有设置的,也就是Controller相关的请求还是走的DataPlane。 想要隔离的话必须设置control.plane.listener.name .

    1. 必须配置control.plane.listener.name
    2. 控制器面板的RequestChannel中的requestQueue不是由queued.max.requests控制的,而是写死的 20. 因为控制类请求不会有那么大的并发
    3. 跟DataPlane相关隔离,互不影响。但是连接限流ConnectionQuotas是共享的,限流的时候,两个是算在一起的
    4. 控制类面板只有一个Acceptor和一个Processor,这个跟数据面板的区别是 DataPlane的Processor可以有多个。
    1. Kafka整个请求流程是什么样子的

    请看上面网络通信总结部分。

    展开全文
  • 分布式系统中进程间通信模型的逆向恢复方法,赵芸,李青山,本文从逆向工程的角度分析了分布式系统中的进程间通信关系,提出了一种分布式系统中进程间通信模型的逆向恢复方法。利用反射植入
  • 为了确定PEBB之间通信的具体要求,必须分析HM-AM-SM体系的通信模型。分析分布式控制系统最常用的方法是采用基于开放系统互连参考模型(open system in-Cerconnection ,OSI)的分析方法。现场总线通信模型从OSI七层模型...
  • Python网络编程——TCP通信模型

    千次阅读 2021-09-11 10:17:43
    1)UDP通信模型 udp通信模型中,在通信开始之前,不需要建立相关的链接(属于无连接通信),只需要发送数据即可,类似于生活中的“写信”。我们都知道,一个人写完信,把信封寄出去,但他并不能知道信封是否能被...

    1、TCP相关介绍

            1)UDP通信模型

            udp通信模型中,在通信开始之前,不需要建立相关的链接(属于无连接通信),只需要发送数据即可,类似于生活中的“写信”。我们都知道,一个人写完信,把信封寄出去,但他并不能知道信封是否能被邮寄到投递人手中,即不能知道对方是否接收到自己发送的数据信息,除非对方成功把回信寄给你,你才能知道对方收到了你的信。所以,udp通信只在乎发送数据,因而该通信模式的速度相对较快。

            2)TCP通信模型

            tcp通信模型中,在通信开始之前,一定要先建立相关的链接(属于面向连接通信),才能发送数据,类似于生活中的“打电话”。通过3次握手,4次挥手方式建立连接,然后就能保持网络通信,直至一方断开连接,即有一方挂掉电话,然后会出现“嘀嘀嘀”的电话断开声音。TCP通信模型相对于UDP通信模型稍微复杂一点。该通信模型区分服务端和客户端比较严格,服务器通过绑定自己的IP,用来监听客户。只要客户端连接了服务端,就能实现网络通信,也可以实现多个客户端连接服务器。所以现在游戏一般都是TCP服务,而一些简单的数据收发是属于UDP服务的。

    2、TCP三次握手和四次挥手

            那么,在进入TCP通信之前,我们需要了解什么是TCP的三次握手和四次挥手,以及为什么TCP需要的三次握手和四次挥手。

    第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

    1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
    2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
    3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
    4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
    6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。 

            因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

     3、代码实现C/S端TCP通信

     需要创建服务器和客户端两个窗口控制台

    import socket
    # 1. 创建socket对象
    import threading
    client = socket.socket()
    server_ip = ('192.168.12.27', 8080)  # 服务器的ip和port
    
    # 2. 链接服务器
    client.connect(server_ip)
    
    # 3. 数据收发
    def recv():
        while True:
            data = client.recv(1024)
            print('收到数据:', data.decode())
    
    # 4.发送方法
    def send():
        while True:
            temp = input('请输入要发送的数据?\n')
            client.send(temp.encode())
            print('发送成功!')
    
    threading.Thread(target=recv).start()  # 开启收数据 线程
    threading.Thread(target=send).start()  # 开启收数据 线程

    4、结果展示

    1)服务器开启

    2)客户端开启 

     3)客户端发送数据到服务器

     4)服务器接收客户端数据

            希望此次分享能给大家带来一些Python网络通信、以及计算机网络方面知识上的帮助(喜欢小编的关注、点赞走一波呦,后期会不定期分享更多Python方向的相关知识)

    展开全文
  • 数字通信基础相关程序代码,包含Matlab仿真程序 包含第4章仿真
  • socket通信模型

    2020-12-08 16:54:32
    socket编程是一门技术,它主要是在网络通信中经常用到。 既然是一门技术,由于现在是面向对象的编程,一些计算机行业的大神通过抽象的理念,在现实中通过反复的理论或者实际的推导,提出了抽象的一些通信协议,基于...

    1. socket简介:

    socket编程是一门技术,它主要是在网络通信中经常用到。
    在这里插入图片描述

    既然是一门技术,由于现在是面向对象的编程,一些计算机行业的大神通过抽象的理念,在现实中通过反复的理论或者实际的推导,提出了抽象的一些通信协议,基于tcp/ip协议,提出大致的构想,一些泛型的程序大牛在这个协议的基础上,将这些抽象化的理念接口化,针对协议提出的每个理念,专门的编写制定的接口,与其协议一一对应,形成了现在的socket标准规范,然后将其接口封装成可以调用的接口,供开发者使用。

    目前,开发者开发出了很多封装的类来完善socket编程,都是更加方便的实现刚开始socket通信的各个环节,所以我们首先必须了解socket的通信原理,只有从本质上理解socket的通信,才可能快速方便的理解socket的各个环节,才能从底层上真正的把握。

    2. 理解socket工作原理

    要理解socket必须的得理解tcp/ip,它们之间好比送信的线路和驿站的作用,比如要建议送信驿站,必须得了解送信的各个细节。

    TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中:

    1. 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
    2. 传输层:TCP,UDP
    3. 网络层:IP,ICMP,OSPF,EIGRP,IGMP
    4. 数据链路层:SLIP,CSLIP,PPP,MTU

    每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的。
    在这里插入图片描述
    通过上面的图形,由于底一层的需要向高一层的提供服务,我们大致的理解应用程序需要传输层的tcp和网络层的ip协议提供服务。

    大致的了解了应用程序和tcpip协议的大致关系,我们只是知道socket编程是在tcp/IP上的网络编程,但是socket在上述的模型的什么位置呢。这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来。

    在这里插入图片描述

    我们可以发现socket就在应用程序的传输层和应用层之间,设计了一个socket抽象层,传输层的底一层的服务提供给socket抽象层,socket抽象层再提供给应用层,问题又来了,应用层和socket抽象层之间和传输层,网络层之间如何通讯的呢,了解这个之前,我们还是回到原点。

    3. 三次"握手"

    要想理解socket编程怎么通过socket关键词实现服务器和客户端通讯,必须得实现的了解tcp/ip是怎么通讯的,在这个的基础上在去理解socket的握手通讯。

    在tcp/ip协议中,tcp通过三次握手建立起一个tcp的链接,大致如下:

    1. 第一次握手:客户端尝试连接服务器,向服务器发送syn包,syn=j,客户端进入SYN_SEND状态等待服务器确认。
    2. 第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
    3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

    三次握手如下图:
    在这里插入图片描述
    根据tcp的三次握手,socket也定义了三次握手,也许是参考tcp的三次握手,一些计算机大神们画出了socket的三次握手的模型图,如下:
    在这里插入图片描述
    在上面图的基础上,如果我们得到上面的图形,需要我们自己开发一些接口,来满足上面的通讯的三次握手,问题就出来了,我们会需要开发哪些函数。

    4. socket的一些接口函数原理

    通过上面的图,我们清楚,我们好比一些泛型的程序员,一些理论提供者提供给了我们上面的图形的理论,我们需要做的就是讲上面的图形的抽象化的东西具体化。

    第一次握手:客户端需要发送一个syn j 包,试着去链接服务器端,于是客户端我们需要提供一个链接函数。

    第二次握手:服务器端需要接收客户端发送过来的syn J+1 包,然后在发送ack包,所以我们需要有服务器端接受处理函数。

    第三次握手:客户端的处理函数和服务器端的处理函数。

    三次握手只是一个数据传输的过程,但是,我们传输前需要一些准备工作,比如将创建一个套接字,收集一些计算机的资源,将一些资源绑定套接字里面,以及接受和发送数据的函数等等,这些功能接口在一起构成了socket的编程。下面大致的按照客户端和服务端将所需的函数详细的列举出来。

    在这里插入图片描述

    上图都概述了socket的通讯原理。


    参考链接:https://www.cnblogs.com/fengff/p/10984251.html

    展开全文
  • 针对空间网络延迟容忍问题, 提出一种用于空间延迟容忍网络(space delay-tolerant network, SDTN)的安全通信模型。该模型采用谓词逻辑的方法, 建立了SDTN有向多径图、安全协议服务集、可靠路径选择服务集、转发能力...
  • 针对基于EPA标准的无线和有线网段的无缝集成问题,探讨了EPA中基于无线的通信模型,即符合无线局域网(IEEE 802.11)和蓝牙标准的无线EPA设备与有线(以太网)EPA设备的通信模型。通过对EPA设备间的通信过程的分析,...
  • 文章提出了一种针对片上网络的组播通信模型,能够为片上网络提供无死锁的通信。该模型能显著减少总通信量,增加通道利用率;在测试模式下,能有效节省测试时间。将该模型仿真应用到二维带环网格拓扑结构的片上网络中...
  • 为了解决Anycast通信模型的扩展局限性,提出了一种在P2P网络中的Anycast通信模型。以Pastry网络为实例,详细讨论与分析了在P2P网络中实现Anycast通信模型的可行性,并且详细阐述了Anycast通信模型在Pastry网络中的...
  • 针对空间网络延迟容忍问题, 提出一种用于空间延迟容忍网络(space delay-tolerant network, SDTN)的安全通信模型。该模型采用谓词逻辑的方法, 建立了SDTN有向多径图、安全协议服务集、可靠路径选择服务集、转发能力...
  • USB通信模型

    2012-04-19 12:50:18
    USB的互连支持数据在 USB主机与 USB设备之间的流动 这一章主要讲述为了简化主机上的 客户软件(Software client)与设备的功能部件(function)之间的通信而必须的主机接口(host interface)
  • 以太网通信
  • 电信设备-一种实现双控制器通信的通信方法及通信模型.zip
  • 通过对多智能体通信方式、拓扑结构、通信协议、通信模型进行分析,着重研究多智能体系统应用层通信模型,提出一种C/S模型与P2P模型相结合的混合网状通信系统。
  • 本文提出了一种新的Anycast加权通信模型,此模型在某种程度上解决了应用层和IP层实现Anycast技术所存在的问题,如扩展性以及客户与服务器通信失败等等,本文对谊Anycast的加权通信模型进行了深入分析和讨论,并验证...
  • 编写Win32程序模拟实现基于Select模型的两台计算机之间的通信,要求编程实现服务器端与客户端之间双向数据传递。客户端向服务器端发送“计算从1到100的奇数和”,服务器回应客户端并给出从1到100的奇数和结果。
  • 异步TCP通信模型

    2012-05-31 23:59:05
    通过select实现的TCP异步通信程序,包括服务端及客户端,双方互发心跳,本端收到后+1回复。
  • 保密通信模型

    千次阅读 2018-09-02 17:22:28
  • 讨论了局域网网络环境中的实时通信过程的模型。采用 Windows的时间中断技术建立了通信过程中相应的几个模型 :对话建立模型、数据发送与接收模型和对话结束模型,以便用于网络中的实时通信、实时演示和实时讨论。
  • 物理层基础 - 通信模型

    千次阅读 2018-02-12 17:44:03
    物理层作为无线通信协议的支撑性底层对通信性能起着至关重要的作用,可以看到几乎所有实现通信系统跨代的技术革新基本上都发生在物理层上,而物理层的底层就是信号的调制和解调,所谓的频分复用,时分复用甚至MIMO...
  • 网络管理通信模型(SNMP协议)
  • Socket的三种通信模型-BIO、NIO和AIO

    千次阅读 2019-08-14 12:57:47
    网络编程的基本模型是C/S模型,即两个进程间的通信;HTTP请求之后,进行域名解析、三次握手建立连接、连接成功之后,套接字进行通信; 传统的就是同步阻塞,双方是输入和输出流同步阻塞通信; 通常由一个独立的...
  • 无线通信系统仿真--C++实用模型书籍,包含所有源代码,书籍清晰
  • 介绍windows网络编程的通信模型及对比,包括介绍同步、异步、阻塞、非阻塞I/O,着重介绍select模型和iocp模型的优缺点和应用场景。
  • Java中的BIO通信模型

    千次阅读 2020-08-10 10:39:15
    在上一篇Linux和Java中的I/O模型中介绍了NIO、BIO模型,本篇文章讲解一下多线程+BIO的通信模型。主流的web服务器Tomcat就是多线程+BIO的通信模型的代表者。 原理图 Server端 Server端即接收消息的那一端。BIO是一种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 491,886
精华内容 196,754
关键字:

通信模型