netty系列之:channel,ServerChannel和netty中的实现

Netty架构篇 - Bootstrap、ServerBootstrap 本文主要分析Bootstrap、ServerBootstrap的相关方法的底层源码。 阅读详情

Python微信订餐小程序课程视频

https://edu.youkuaiyun.com/course/detail/36074

Python实战量化交易理财系统

https://edu.youkuaiyun.com/course/detail/35475
目录* 简介

简介

我们知道channel是netty中用于沟通ByteBuf和Event的桥梁,在netty服务的创建过程中,不管是客户端的Bootstrap还是服务器端的ServerBootstrap,都需要调用channel方法来指定对应的channel类型。

那么netty中channel到底有哪些类型呢?他们具体是如何工作的呢?一起来看看。

channel和ServerChannel

Channel在netty中是一个interface,在Channel中定义了很多非常有用的方法。通常来说如果是客户端的话,对应的channel就是普通的channel。如果是服务器端的话,对应的channel就应该是ServerChannel。

那么客户端channel和服务器端channel有什么区别呢?我们先来看下ServerChannel的定义:

public interface ServerChannel extends Channel {
    // This is a tag interface.
}

可以看到ServerChannel继承自Channel,表示服务端的Channel也是Channel的一种。

但是很奇怪的是,你可以看到ServerChannel中并没有新增任何新的方法。也就是说ServerChannel和Channel在定义上本质是一样的。你可以把ServerChannel看做是一个tag interface而已。

那么channel和ServerChannel有什么联系呢?

我们知道在Channel中定义了一个parent方法:

Channel parent();

这个parent方法返回的是该channel的父channel。我们以最简单的LocalChannel和LocalServerChannel为例,来查看一下他们的父子关系到底是怎么创建的。

首先parent的值是通过LocalChannel和LocalServerChannel的公共父类AbstractChannel来实现的:

    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }

对于LocalChannel来说,可以通过它的构造函数来设置parent channel:

    protected LocalChannel(LocalServerChannel parent, LocalChannel peer) {
        super(parent);
        config().setAllocator(new PreferHeapByteBufAllocator(config.getAllocator()));
        this.peer = peer;
        localAddress = parent.localAddress();
        remoteAddress = peer.localAddress();
    }

我们知道当client端想要连接到server端的时候,需要调用client channel的connect方法,对于LocalChannel来说,它的connect方法实际上调用的是pipeline的connect方法:

public ChannelFuture connect(SocketAddress remoteAddress) {
        return pipeline.connect(remoteAddress);
    }

最终会调用LocalChannel中的LocalUnsafe.connect方法。

而在LocalUnsafe.connect方法中又会调用serverChannel.serve方法。

serverChannel的newLocalChannel方法会创建新的LocalChannel并返回:

    protected LocalChannel newLocalChannel(LocalChannel peer) {
        return new LocalChannel(this, peer);
    }

这里使用newLocalChannel方法创建的LocalChannel就是serverChannel的子channel。

最后返回的LocalChannel会作为client端LocalChannel的peer channel而存在。

netty中channel的实现

在netty中channel和Serverchannel有很多个实现类,用来完成不同的业务功能。

为了循序渐进一步步了解netty中channel的秘密,这里我们先来探讨一下netty中channel的基本实现LocalChannel和LocalServerChannel的工作原理。

下图是LocalChannel和LocalServerChannel的主要继承和依赖关系:


从图中可以看到,LocalChannel继承自AbstractChannel而LocalServerChannel则继承自AbstractServerChannel。

因为ServerChannel继承自Channel,所以很自然的AbstractServerChannel又继承自AbstractChannel。

接下来,我们通过对比分析AbstractChannel和AbstractServerChannel,LocalChannel和LocalServerChannel来一探netty中channel实现的底层原理。

AbstractChannel和AbstractServerChannel

AbstractChannel是对Channel的最基本的实现。先来看下AbstractChannel中都有那些功能。

首先AbstractChannel中定义了Channel接口中要返回的一些和channel相关的基本属性,包括父channel,channel id,pipline,localAddress,remoteAddress,eventLoop等,如下所示:

    private final Channel parent;
    private final ChannelId id;
    private final DefaultChannelPipeline pipeline;
    private volatile SocketAddress localAddress;
    private volatile SocketAddress remoteAddress;
    private volatile EventLoop eventLoop;

    private final Unsafe unsafe;

要注意的是AbstractChannel中还有一个非常中要的Unsafe属性。

Unsafe本身就是Channel接口中定义的一个内部接口,它的作用就是为各个不同类型的transport提供特定的实现。

从名字可以看出Unsafe是一个不安全的实现,它只是在netty的源代码中使用,它是不能出现在用户代码中的。或者你可以将Unsafe看做是底层的实现,而包裹他的AbstractChannel或者其他的Channel是对底层实现的封装,对于普通用户来说,他们只需要使用Channel就可以了,并不需要深入到更底层的内容。

另外,对于Unsafe来说,除了下面几个方法之外,剩余的方法必须从 I/O thread中调用:

localAddress()
remoteAddress()
closeForcibly()
register(EventLoop, ChannelPromise)
deregister(ChannelPromise)
voidPromise()

和一些基本的状态相关的数据:

private volatile boolean registered;
private boolean closeInitiated;

除了基本的属性设置和读取之外,我们channel中最终要的方法主要有下面几个:

  1. 用于建立服务器端服务的bind方法:
public ChannelFuture bind(SocketAddress localAddress) {
        return pipeline.bind(localAddress);
    }

  1. 用于客户端建立和服务器端连接的connect方法:
public ChannelFuture connect(SocketAddress remoteAddress) {
        return pipeline.connect(remoteAddress);
    }

  1. 断开连接的disconnect方法:
public ChannelFuture disconnect() {
        return pipeline.disconnect();
    }

  1. 关闭channel的close方法:
public ChannelFuture close() {
        return pipeline.close();
    }

  1. 取消注册的deregister方法:
public ChannelFuture deregister() {
        return pipeline.deregister();
    }

  1. 刷新数据的flush方法:
    public Channel flush() {
        pipeline.flush();
        return this;
    }

  1. 读取数据的read方法:
    public Channel read() {
        pipeline.read();
        return this;
    }

  1. 写入数据的方法:
    public ChannelFuture write(Object msg) {
        return pipeline.write(msg);
    }

可以看到这些channel中的读写和绑定工作都是由和channel相关的pipeline来执行的。

其实也很好理解,channel只是一个通道,和数据相关的操作,还是需要在管道中执行。

我们以bind方法为例子,看一下AbstractChannel中的pipline是怎么实现的。

在AbstractChannel中,默认的pipeline是DefaultChannelPipeline,它的bind方法如下:

        public void bind(
 ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) {
            unsafe.bind(localAddress, promise);
        }

这里的unsafe实际上就是AbstractChannel中的unsafe,unsafe中的bind方法最终会调用AbstractChannel中的dobind方法:

protected abstract void doBind(SocketAddress localAddress) throws Exception;

所以归根到底,如果是基于AbstractChannel的各种实现,那么只需要实现它的这些do*方法即可。

好了,AbstractChannel的介绍完毕了。 我们再来看一下AbstractServerChannel。AbstractServerChannel继承自AbstractChannel并且实现了ServerChannel接口。

public abstract class AbstractServerChannel extends AbstractChannel implements ServerChannel 

我们知道ServerChannel和Channel实际上是相同的,所以AbstractServerChannel只是在AbstractChannel的实现上进行了一些调整。

在AbstractServerChannel中,我们一起来观察一下AbstractServerChannel和AbstractChannel到底有什么不同。

首先是AbstractServerChannel的构造函数:

protected AbstractServerChannel() {
        super(null);
    }

构造函数中,super的parent channel是null,表示ServerChannel本身并不存在父channel,这是ServerChannel和client channel
的第一个不同之处。因为server channel可以通过worker event loop来接受client channel,所以server channel是client channel的父channel。

另外,我们还观察几个方法的实现:

public SocketAddress remoteAddress() {
        return null;
    }

对于ServerChannel来说不需要主动连接到远程的Server,所以并没有remoteAddress。

另外,因为断开连接是由client端主动调用的,所以server channel的doDisconnect会抛出不支持该操作的异常:

    protected void doDisconnect() throws Exception {
        throw new UnsupportedOperationException();
    }

同时ServerChannel只是用来负责accept和client channel建立关联关系,所以server channel本身并不支持向channel内进行的write操作,所以这个doWrite方法也是不支持的:

    protected void doWrite(ChannelOutboundBuffer in) throws Exception {
        throw new UnsupportedOperationException();
    }

最后ServerChannel只支持bind操作,所以DefaultServerUnsafe中的connect方法也会抛出UnsupportedOperationException.

LocalChannel和LocalServerChannel

LocalChannel和LocalServerChannel是AbstractChannel和AbstractServerChannel的最基本的实现。从名字就可以看出来,这两个Channel是本地channel,我们来看一下这两个Channel的具体实现。

首先我们来看一下LocalChannel,LocalChannel有几点对AbstractChannel的扩展。

第一个扩展点是LocalChannel中添加了channel的几个状态:

private enum State { OPEN, BOUND, CONNECTED, CLOSED }

通过不同的状态,可以对channel进行更加细粒度的控制。

另外LocalChannel中添加了一个非常重要的属性:

private volatile LocalChannel peer;

因为LocalChannel表示的是客户端channel,所以这个peer表示的是client channel对等的server channel。接下来我们看一下具体的实现。

首先是LocalChannel的构造函数:

    protected LocalChannel(LocalServerChannel parent, LocalChannel peer) {
        super(parent);
        config().setAllocator(new PreferHeapByteBufAllocator(config.getAllocator()));
        this.peer = peer;
        localAddress = parent.localAddress();
        remoteAddress = peer.localAddress();
    }

LocalChannel可以接受一个LocalServerChannel作为它的parent,还有一个LocalChannel作为它的对等channel。

那么这个peer是怎么创建的呢?

我们来看一下LocalUnsafe中connect的逻辑。

            if (state != State.BOUND) {
                // Not bound yet and no localAddress specified - get one.
                if (localAddress == null) {
                    localAddress = new LocalAddress(LocalChannel.this);
                }
            }

            if (localAddress != null) {
                try {
                    doBind(localAddress);
                } catch (Throwable t) {
                    safeSetFailure(promise, t);
                    close(voidPromise());
                    return;
                }
            }

首先判断当前channel的状态,如果是非绑定状态,那么需要进行绑定操作。首先根据传入的LocalChannel创建对应的LocalAddress。

这个LocalAddress只是LocalChannel的一种表现形式,并没有什么特别的功能。

我们来看一下这个doBind方法:

    protected void doBind(SocketAddress localAddress) throws Exception {
        this.localAddress =
                LocalChannelRegistry.register(this, this.localAddress,
                        localAddress);
        state = State.BOUND;
    }

LocalChannelRegistry中维护了一个static的map,这个map中存放的就是注册过的Channel.

这里注册是为了在后面方便的拿到对应的channel。

注册好localChannel之后,接下来就是根据注册好的remoteAddress来获取对应的LocalServerChannel,最后调用LocalServerChannel的serve方法创建一个新的peer channel:

Channel boundChannel = LocalChannelRegistry.get(remoteAddress);
            if (!(boundChannel instanceof LocalServerChannel)) {
                Exception cause = new ConnectException("connection refused: " + remoteAddress);
                safeSetFailure(promise, cause);
                close(voidPromise());
                return;
            }

            LocalServerChannel serverChannel = (LocalServerChannel) boundChannel;
            peer = serverChannel.serve(LocalChannel.this);

serve方法首先会创建一个新的LocalChannel:

    protected LocalChannel newLocalChannel(LocalChannel peer) {
        return new LocalChannel(this, peer);
    }

如果我们把之前的Localchannel称为channelA,这里创建的新的LocalChannel称为channelB。那么最后的结果就是channelA的peer是channelB,而channelB的parent是LocalServerChannel,channelB的peer是channelA。

这样就构成了一个对等channel之间的关系。

接下来我们看下localChannel的read和write到底是怎么工作的。

首先看一下LocalChannel的doWrite方法:

Object msg = in.current();
...
peer.inboundBuffer.add(ReferenceCountUtil.retain(msg));
in.remove();
...
finishPeerRead(peer);

首先从ChannelOutboundBuffer拿到要写入的msg,将其加入peer的inboundBuffer中,最后调用finishPeerRead方法。

从方法名字可以看出finishPeerRead就是调用peer的read方法。

事实上该方法会调用peer的readInbound方法,从刚刚写入的inboundBuffer中读取消息:

    private void readInbound() {
        RecvByteBufAllocator.Handle handle = unsafe().recvBufAllocHandle();
        handle.reset(config());
        ChannelPipeline pipeline = pipeline();
        do {
            Object received = inboundBuffer.poll();
            if (received == null) {
                break;
            }
            pipeline.fireChannelRead(received);
        } while (handle.continueReading());

        pipeline.fireChannelReadComplete();
    }

所以,对于localChannel来说,它的写实际上写入到peer的inboundBuffer中。然后再调用peer的读方法,从inboundBuffer中读取数据。

相较于localChannel来说,localServerChannel多了一个serve方法,用来创建peer channel,并调用readInbound开始从inboundBuffer中读取数据。

总结

本章详细介绍了channel和serverChannel的区别,和他们的最简单的本地实现。希望大家对channel和serverChannel的工作原理有了最基本的了解。

本文已收录于 http://www.flydean.com/04-2-netty-channel-vs-serverchannel-md/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

霍尔安装歪了也能用?揭秘无感FOC中的‘霍尔自学习’黑科技,实现信号线自适应 本文揭秘了无感FOC中的‘霍尔自学习’黑科技,即使霍尔安装歪了或信号线接错,电机仍能平稳运转。该技术通过算法创新解决了传统霍尔方案的安装公差、接线容错和校准成本问题,显著提升了电机控制的可靠性和效率。文章详细解析了自学习算法的实现架构、关键技术及工程实践中的优化方案,展示了其在工业应用中的卓越性能。 阅读详情

相关推荐

电机转矩、功率与转速:核心关系、公式推导与工程应用指南

在电气传动与自动化控制领域,理解旋转机械的核心物理量是进行设备选型、系统设计和故障诊断的基础。转矩、功率和转速构成了描述电机性能的“铁三角”,它们之间通过经典的物理公式紧密关联。从原理上讲,功率是单位时间内做功的能力,转矩是产生旋转运动的力矩,而转速则决定了运动快慢。这三者的关系(P = T × n / 9550)不仅是理论核心,更是工程实践中的关键计算工具,直接关系到电机的驱动能力、能耗与系统匹配。其技术价值在于,它为从微型伺服电机到大型工业传动系统的设计提供了统一的量化分析框架。在应用场景上,无论是为输

weixin_29184371的博客 264

Java Netty 学习(八) - Netty的Channel

在普通IO中,通过把机器传输抽象成java.net.Socket流,也就是Socket和ServerSocket 到NIO时,则变为了java.nio.channels.Channel,也是作为传输的管道,具体可看Java Netty 学习(四) - NIO基础知识Channel和Pipe 那今天就一起学习Netty中的Channel,看它又是一种怎么样的设计形式。 介绍 在netty的Chann...

anLA_的专栏 3785

本届挑战赛亚军方案:基于大模型和多AGENT协同的运维

我们分别构建了异常检测基础模型,一旦系统接受到异常即会通知LLM主管Agent,主管Agent对异常问题进行决策与子领域Agent进行桥接,多个子领域Agent协同工作,实现运维故障自动诊断和多个任务模型的编排,提升运维效率。

weixin_52705010的博客 2295

netty系列之:netty中各不同种类的channel详解

文章目录简介ServerChannel和它的类型Epoll和KqueueAbstractServerChannelServerSocketChannelServerDomainSocketChannelSctpServerChannelChannel和它的类型UnixChannelSctpChannelDatagramChannelDomainDatagramChannelDuplexChannelAbstractChannel总结 简介 channel是连接客户端和服务器端的桥梁,在netty中我们最常用

程序那些事 5424

Unity Sprite Editor切片功能详解:如何快速将一张大图拆分成多个小图(附常见问题解决)

本文详细解析了Unity Sprite Editor的切片功能,指导开发者如何高效地将一张大图拆分为多个独立小图。文章涵盖了自动与手动切片操作步骤、轴心点设置、子精灵命名管理等核心技巧,并针对切片错位、性能优化等常见问题提供了实用解决方案,帮助提升2D游戏资源处理效率。

i0j1k2l3m的博客 648

Delta机器人:运动学正反解分析

Delta机器人:运动学正反解分析 一、Delta机构简介 Delta机构是并联机构中的一种典型机构,起原始结构如图1所示。Delta机构由R.Clavel 博士在 1985年发明,是现在并联机器人中使用最多的一种,具备了并联机构所特有的优点,负载能力强、效率高、末端执行器精度高、运动惯性小,可以高速稳定运动等。因此在机器人领域获得了越来越广泛的应用。以实现高速、精准、高效的运动。           &n

花洛兮灬 3万+

LocalChannel in Netty

缘起在工作中,有一个feature用到了netty的LocalChannel的功能,之前由于时间太紧没有机会总结下这个LocalChannel,今天有时间就过来写一下。LocalChannel介绍LcoalChannel是Netty提供的用来在同一个JVM内部实现client和server之间通信的transport。它的实现主要是通过内存里的对象作为通信介质,不会像NIO下的channel,会占用

会飞的大老虎 2932

langchain入门学习笔记

langchain快速入门

1734

netty系列之ChannelOption

1、概述 在netty 启动的时候会设置相关的ChannelOption, 无论是在ServerBootstrap还是在Bootstrap, 接下来解释一下常用的ChannelOption 2、常用ChannelOption ChannelOption.SO_BACKLOG (一般用于option–>boss) BACKLOG用于构造服务端套接字ServerSocket对象,标识当服...

zhongzunfa的专栏 9441

置顶必读(2) |《YOLOv8实战:从入门到深度优化》总目录导航 & 学习路线指南(持续更新中)

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 28万+

k8s篇之underlay网络和overlay区别

underlay和overlay

小橙子的笔记屋 2144

netty系列之:channel和channelGroup

文章目录简介神龙见首不见尾的channelchannel和channelGroupchannelGroup的基本使用将关闭的channel自动移出同时关闭serverChannel和acceptedChannelChannelGroupFuture总结 简介 channel是netty中数据传输和数据处理的渠道,也是netty程序中不可或缺的一环。在netty中channel是一个接口,针对不同的数据类型或者协议channel会有具体的不同实现。 虽然channel很重要,但是在代码中确实很神秘,基本上我们

程序那些事 6995

PCL 提取两片点云的非重叠部分【2025最新版】

PCL 提取两片点云的非重叠部分。博客长期更新,本文最近一次更新时间为:2025年9月1日。

点云侠的博客 36万+

Netty是如何实现线程和Channel唯一绑定的

netty的线程模型对一个channel来说是单线程的,也就是说这个channel的所有读写事件都是同一个线程执行的,避免了多线程产生的并发问题.而一个eventloop是可以被多个channel绑定的,那么每次服务器连接一个channel之时,netty时如何知道使用哪个线程的呢? 本文描述背景假设对netty的使用比较熟悉,例如 ChannelContext,ChannelPipeline,...

The Hot Java 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Netty设置option警告Unknown channel option

本文使用环境版本是 netty 4.1.36.Final jdk 1.8 在设置netty服务端的option时,设置了如下参数。 server.group(boss,worker)//设置时间循环对象,前者用来处理accept事件,后者用于处理已经建立的连接的io //Server是NioServerSocketChannel 客户端是NioSocketChann...

Sail__的专栏 2万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Netty中的Option和ChildOption参数解析

前言 Netty中的Option和ChildOption的区别: 1.Netty中的option主要是设置的ServerChannel的一些选项,而childOption主要是设置的ServerChannel的子Channel的选项。 2.如果是在客户端,因为是Bootstrap,只会有option而没有childOption,所以设置的是客户端Chann...

SmallCatBaby的博客 6257

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

[netty5: Channel & ServerChannel]-创建流程

{// ...// ...boolean supportingDisconnect, // false => 该通道是否支持 disconnect() 操作,并允许用户在断开连接后再次调用 Channel#connect(SocketAddress),例如 UDP/IP 协议) {try {// 为ServerSocketChannel设置非堵塞模式try {ch.close();

... 347

netty源码阅读之ServerChannel初始化与注册。

netty源码阅读之ServerChannel初始化与注册。 上一章看了ServerBootstrap类的主要方法大致了解主要干了啥,现在开始顺着demo代码ChannelFuture f = bootstrap.bind(7777).sync();debug下去。仔细看一看这个过程主要做了哪些事情。 跟进bind()方法 主要看 initAndRegister()方法,看是初始化谁,又注册谁。 public ChannelFuture bind(SocketAddress localAddress) {

m0_48187193的博客 416

Netty 基本组件小结--Channel、EventLoop、Bootstrap等

本文源自转载:Netty基本组件小结 Netty 基本组件小结--Channel、EventLoop、Bootstrap等 一、什么是Channel? Channel按照其字面意思非常容易理解,那就是"管道"。自来水通遍千家万户需要架设管道,暖气也需要架设管道,同样,网络通信也需要架设管道,这个管道就是我们的Socket。我们发现,自来水管道中流通的是自来水,暖气管道中流通的是暖气,那么Socket中流通的当属我们的字节流了。 说了这么多,那么到底什么是Channel呢?小编理解,Channel就是

dongcheng_2015的博客 574

netty系列之:EventLoop,EventLoopGroup和netty的默认实现

Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/course/detail/35475 目录* 简介 EventLoopGroup和EventLoop EventLoopGroup在netty中的默认实现 EventLoop在netty中的默认实现 总结 简介 在netty中不管是服务器端的ServerBootstrap还是客户端的Bootstrap,在创建的

xuhss_com的博客 212

Netty-9 Channel和UnSafe

一、Channel简介 Channel是Netty的网络抽象类,聚合了很多的功能,包括网络读、写,客户端发起连接,主动关闭连接,链路关闭,获取通讯双方的网络地址等。也包括了Netty框架自身的一些功能,如获取该Channel的EventLoop,获取缓冲分配器ByteBufferAllocator和pipeline等等。 二、Channel功能介绍 以上是Channel接口提供的一些方法,很多比...

mail_liuxing的专栏 411

Netty中的基本组件及关系

概述    这篇文章主要是用来介绍netty中常用的一些组件,以及这些组件之间的存在关系Channel  ----SocketEventLoop ----控制流,多线程处理,并发;ChannelHandler和ChannelPipelineBootstrap 和 ServerBootstrapChannel 接口     基本的I/O操作,在基于java 的网络编程中,其基本的构造是 Socket...

summerZBH123的博客 3722

Netty入门——基于NIO实现机器客服案例

netty入门

weixin_43626356的博客 1035

netty学习之ServerChannel

首先我们先来看serverchannel的类继承层次,然后再一个一个的研究。    现在我们来挨个的介绍各个类。     AbstractChannel应该是整个Channel子类的父类,这个里面有一个static的变量allChannels,这个里面放着所有的channel,现在还不能体会放这个得好处。里面感觉没有什么特殊的,allocateId这个方法应该是给channel分配一个id...

勤奋的asialee的博客 524

Java NIO三大组件:Buffer、Channel、Selector实现多路复用网络通信,以及Netty通信

在JavaSE的学习中,我们了解了如何使用IO进行数据传输,Java IO是阻塞的,如果在一次读写数据调用时数据还没有准备好,或者目前不可写,那么读写操作就会被阻塞直到数据准备好或目标可写为止。Java NIO则是非阻塞的,每一次数据读写调用都会立即返回,并将目前可读(或可写)的内容写入缓冲区或者从缓冲区中输出,即使当前没有可用数据,调用仍然会立即返回并且不对缓冲区做任何操作。NIO框架是在JDK1.4推出的,它的出现就是为了解决传统IO的不足。

m0_47518801的博客 207
上一篇: 2022年了有哪些值得推荐的.NET ORM框架?
下一篇: Python 基于 TCP 传输协议的网络通信实现
pythonxxoo
博客等级 码龄5年 337粉丝 670原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值