Netty入门学习笔记(一)

【Netty入门教程】Netty基础篇之入门详情介绍 本文主要讲述Netty框架的一些特性以及重要组件,希望看完之后能对Netty框架有一个比较直观的感受,希望能帮助读者快速入门Netty,减少一些弯路。 Netty是 一个异步事件驱动的网络应用程序框架,用于**快速开发可维护的高性能协议服务器和客户端。 Netty是一个NIO客户端-服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它大大简化和简化了TCP和UDP套接字服务器等网络编程。 阅读详情

Netty 4.1 入门学习笔记

参考博客:bugstack虫洞栈
本笔记基于 Netty 4.1 版本,通过 12 个渐进式项目,从零开始学习 Netty 网络编程框架。
代码来源:https://github.com/fuzhengwei/itstack-demo-netty


📚 学习路线图

Netty入门学习路线
│
├─ 阶段一:服务端基础(项目 1-01 ~ 1-06)
│  ├─ 1-01:搭建最基础的Netty服务端
│  ├─ 1-02:手动解码接收数据
│  ├─ 1-03:使用内置解码器
│  ├─ 1-04:手动编码发送数据
│  ├─ 1-05:使用内置编码器
│  └─ 1-06:实现群发消息功能
│
├─ 阶段二:客户端实现(项目 1-07 ~ 1-08)
│  ├─ 1-07:实现基础Netty客户端
│  └─ 1-08:实现完整的收发功能
│
└─ 阶段三:高级特性(项目 1-09 ~ 1-12)
   ├─ 1-09:自定义编解码器
   ├─ 1-10:入站/出站处理器
   ├─ 1-11:UDP通信实现
   └─ 1-12:HTTP服务器实现

📖 目录


阶段一:服务端基础

在这个阶段,我们将从零开始搭建Netty服务端,逐步学习数据的接收和发送,最终实现一个功能完整的服务端。

项目 1-01:搭建最基础的Netty服务端

📌 项目目标

搭建一个最基础的Netty服务端,理解Netty的启动流程和核心组件。此时的服务端只能监听连接,不能接收数据、不能向客户端发送数据、没有业务处理逻辑。

🔑 核心知识点
  1. EventLoopGroup:事件循环组,负责处理I/O操作

    • parentGroup(Boss线程组):负责接收客户端连接
    • childGroup(Worker线程组):负责处理已建立连接的I/O操作
  2. ServerBootstrap:服务端启动辅助类,用于配置服务端参数

  3. Channel:网络通信的载体,代表一个连接

  4. ChannelInitializer:Channel初始化器,用于配置Pipeline

  5. ChannelHandler:业务处理器,处理I/O事件

💻 核心代码解析

NettyServer.java - 服务端启动类

public class NettyServer {

    public static void main(String[] args) {
        new NettyServer().bing(7397);
    }

    private void bing(int port) {
        // ============ 第一步:创建线程组 ============
        // parentGroup(Boss线程组):负责接收客户端的连接请求
        // 默认线程数 = CPU核心数 * 2
        // 作用:类似餐厅的迎宾员,专门负责迎接新客人(接收新连接)
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        
        // childGroup(Worker线程组):负责处理已建立连接的IO读写操作
        // 默认线程数 = CPU核心数 * 2
        // 作用:类似餐厅的服务员,负责为客人提供服务(处理数据读写)
        EventLoopGroup childGroup = new NioEventLoopGroup();
        
        try {
            // ============ 第二步:创建服务端启动助手 ============
            ServerBootstrap b = new ServerBootstrap();
            
            // ============ 第三步:配置服务端参数 ============
            b.group(parentGroup, childGroup)                  // 配置主从Reactor线程模型
                    .channel(NioServerSocketChannel.class)    // 设置NIO模式的ServerSocketChannel(非阻塞)
                    .option(ChannelOption.SO_BACKLOG, 128)    // 设置服务端参数:TCP连接队列大小为128
                    .childHandler(new MyChannelInitializer()); // 设置子通道的处理器(每个客户端连接都会创建一个)
            
            // ============ 第四步:绑定端口并启动服务 ============
            // bind(port):异步绑定端口
            // sync():同步等待绑定完成,如果不调用sync(),bind()会立即返回
            ChannelFuture f = b.bind(port).sync();
            System.out.println("服务端启动成功,端口:" + port);
            
            // ============ 第五步:等待服务端监听端口关闭 ============
            // closeFuture():获取Channel关闭的Future对象
            // sync():阻塞等待服务器关闭(如果不调用,程序会立即执行到finally导致服务关闭)
            f.channel().closeFuture().sync();
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // ============ 第六步:优雅关闭线程组,释放资源 ============
            // shutdownGracefully():优雅关闭,会等待任务执行完成
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }

    }

}

MyChannelInitializer.java - Channel初始化器

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel channel) {
        // 此时Pipeline中没有添加任何Handler
        // 所以服务端只能接收连接,不能处理数据
    }
}
🎯 运行效果
  • 启动服务端后,可以使用Telnet或Socket客户端连接
  • 服务端能够接收连接,但不会有任何响应
  • 这是最基础的Netty服务端,为后续功能打下基础
📊 知识演进
项目1-01:只能监听连接
    ↓
项目1-02:增加数据接收功能

项目 1-02:手动解码接收数据

📌 项目目标

在1-01项目的基础上,添加数据接收功能,学习如何处理客户端发送的数据。通过手动处理ByteBuf,理解数据解码的底层原理。

🔑 核心知识点
  1. ByteBuf:Netty的字节缓冲区,类似于Java NIO的ByteBuffer,但更强大

    • readableBytes():获取可读字节数
    • readBytes(byte[]):读取字节到数组
  2. channelRead():当Channel有数据可读时触发

  3. 手动解码:将ByteBuf转换为业务需要的数据类型

💻 核心代码解析

MyServerHandler.java - 业务处理器

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 第一步:将msg转换为ByteBuf(Netty的字节缓冲区)
        // ByteBuf类似于Java NIO的ByteBuffer,但功能更强大
        ByteBuf buf = (ByteBuf) msg;
        
        // 第二步:创建字节数组,大小为可读字节数
        // readableBytes():返回当前可读的字节数
        byte[] msgByte = new byte[buf.readableBytes()];
        
        // 第三步:从ByteBuf中读取数据到字节数组
        // readBytes():读取数据并移动读指针
        buf.readBytes(msgByte);
        
        // 第四步:将字节数组转换为字符串并打印
        System.out.print(new Date() + " 接收到消息:");
        System.out.println(new String(msgByte, Charset.forName("UTF-8")));
    }

MyChannelInitializer.java - 添加Handler

@Override
protected void initChannel(SocketChannel channel) {
    // 将自定义的Handler添加到Pipeline中
    channel.pipeline().addLast(new MyServerHandler());
}
🎯 运行效果
  • 客户端发送消息后,服务端能够接收并打印
  • 服务端控制台输出:服务端接收到消息:Hello Netty
📊 与项目1-01的对比
功能项目1-01项目1-02
接收连接✅✅
接收数据❌✅
发送数据❌❌
解码方式-手动解码
💡 存在的问题
  • 手动处理ByteBuf比较繁琐
  • 需要自己处理字符编码
  • 没有处理TCP粘包/拆包问题

项目 1-03:使用内置解码器

📌 项目目标

在1-02项目基础上引入解码器,使用Netty内置的解码器,让代码更简洁优雅。直接接收String对象而不是ByteBuf,学习Netty常用解码器,解决TCP粘包/拆包问题。

🔑 核心知识点
  1. LineBasedFrameDecoder:基于换行符的解码器

    • 自动处理TCP粘包/拆包问题
    • 以\n或\r\n为分隔符
  2. StringDecoder:字符串解码器

    • 将ByteBuf自动转换为String
    • 支持指定字符编码
  3. Pipeline处理顺序:解码器 → 业务Handler

💻 核心代码解析

MyChannelInitializer.java - 添加解码器

@Override
protected void initChannel(SocketChannel channel) {
    /* ============ 配置解码器(核心变化)============ */

    // 第一步:添加帧解码器 - LineBasedFrameDecoder(基于换行符的帧解码器)
    // 作用:解决TCP粘包/拆包问题,按换行符(\n或\r\n)分割数据帧
    // 参数1024:单行最大长度,超过会抛异常(防止恶意攻击)
    // 工作原理:接收 "Hello\nWorld\n" → 输出 "Hello" 和 "World" 两个独立的帧
    channel.pipeline().addLast(new LineBasedFrameDecoder(1024));

    // 其他可选的帧解码器(根据实际需求选择):
    // 1. 基于指定分隔符:DelimiterBasedFrameDecoder
    //    channel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, false, Delimiters.lineDelimiter()));
    // 2. 基于固定长度:FixedLengthFrameDecoder(每4个字节一个帧)
    //    channel.pipeline().addLast(new FixedLengthFrameDecoder(4));
    // 3. 基于长度字段:LengthFieldBasedFrameDecoder(常用于自定义协议)

    // 第二步:添加字符串解码器 - StringDecoder
    // 作用:将ByteBuf自动转换为String对象
    // 参数:字符编码(GBK或UTF-8),需要与客户端编码一致
    // 工作原理:ByteBuf → String(自动完成,不需要手动转换)
    channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));

    // 第三步:添加业务处理器
    // 此时channelRead()方法接收到的msg已经是String类型
    channel.pipeline().addLast(new MyServerHandler());

}

MyServerHandler.java - 简化的业务处理器

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    // msg已经是String类型,可以直接使用
    // 解码器链:ByteBuf → LineBasedFrameDecoder → StringDecoder → String
    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) 
                       + " 接收到消息:" + msg);
}
🎯 运行效果
  • 代码更简洁,不需要手动处理ByteBuf
  • 自动解决TCP粘包/拆包问题
  • 直接接收String对象
📊 与项目1-02的对比
功能项目1-02项目1-03
解码方式手动解码内置解码器
代码复杂度高低
粘包/拆包未处理自动处理
接收类型ByteBufString
💡 常用解码器
  • LineBasedFrameDecoder:基于换行符
  • DelimiterBasedFrameDecoder:基于自定义分隔符
  • FixedLengthFrameDecoder:固定长度
  • LengthFieldBasedFrameDecoder:基于长度字段

项目 1-04:手动编码发送数据

📌 项目目标

在1-03项目基础上增加了发送消息功能,学习如何向客户端发送数据。此时没有引入编码器,需要手动转换类型。

🔑 核心知识点
  1. ChannelHandlerContext.writeAndFlush():发送数据并刷新缓冲区

    • write():写入缓冲区
    • flush():刷新缓冲区,真正发送数据
    • writeAndFlush():写入并刷新
  2. Unpooled.copiedBuffer():创建ByteBuf

    • 将字符串转换为ByteBuf
  3. 手动编码:将业务数据转换为ByteBuf

💻 核心代码解析

MyServerHandler.java - 发送数据

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    // 1. 接收客户端消息
    String message = (String) msg;
    System.out.println("服务端接收到消息:" + message);
    
    // 2. 手动编码:将String转换为ByteBuf
    String response = "服务端收到:" + message + "\r\n";
    ByteBuf buf = Unpooled.copiedBuffer(response.getBytes(Charset.forName("GBK")));
    
    // 3. 发送数据
    ctx.writeAndFlush(buf);
}
🎯 运行效果
  • 服务端接收到消息后,会回复客户端
  • 客户端能够收到服务端的响应
📊 与项目1-03的对比
功能项目1-03项目1-04
接收数据✅✅
发送数据❌✅
编码方式-手动编码
💡 存在的问题
  • 手动编码比较繁琐
  • 需要自己创建ByteBuf
  • 代码不够优雅

项目 1-05:使用内置编码器

📌 项目目标

在1-04项目基础上引入编码器,实现收发数据都使用String,代码达到最简洁优雅的状态。

🔑 核心知识点
  1. StringEncoder:字符串编码器

    • 将String自动转换为ByteBuf
    • 支持指定字符编码
  2. 编解码器配置顺序:

    • 解码器:LineBasedFrameDecoder → StringDecoder
    • 编码器:StringEncoder
  3. Pipeline双向处理:

    • 入站(Inbound):解码器处理接收的数据
    • 出站(Outbound):编码器处理发送的数据
💻 核心代码解析

MyChannelInitializer.java - 添加编码器

@Override
protected void initChannel(SocketChannel channel) {
    /* ============ 配置编解码器(完整版)============ */

    // 第一步:添加帧解码器 - LineBasedFrameDecoder
    // 作用:解决TCP粘包/拆包问题,按换行符分割数据帧
    channel.pipeline().addLast(new LineBasedFrameDecoder(1024));

    // 第二步:添加字符串解码器 - StringDecoder(入站)
    // 作用:将接收到的ByteBuf自动转换为String
    // 处理方向:ByteBuf → String(客户端发来的数据)
    channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));

    // ⭐ 第三步:添加字符串编码器 - StringEncoder(出站,核心新增)
    // 作用:将要发送的String自动转换为ByteBuf
    // 处理方向:String → ByteBuf(发送给客户端的数据)
    // 优势:不需要手动创建ByteBuf,代码更简洁
    channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));

    // 第四步:添加业务处理器
    // 此时Handler中可以直接使用String收发数据,无需关心编解码细节
    channel.pipeline().addLast(new MyServerHandler());

    /* ============ Pipeline完整处理链 ============
         * 
         * 【入站方向 - 接收数据】
         * 客户端数据 → LineBasedFrameDecoder(分帧)
         *           → StringDecoder(ByteBuf转String)
         *           → MyServerHandler(业务处理)
         * 
         * 【出站方向 - 发送数据】
         * MyServerHandler(业务处理)
         *           → StringEncoder(String转ByteBuf)
         *           → 网络发送
         */
}

MyServerHandler.java - 简化的发送代码

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    // 1. 接收消息(已经是String类型)
    String message = (String) msg;
    System.out.println("服务端接收到消息:" + message);
    
    // 2. 直接发送String,编码器会自动转换为ByteBuf
    String response = "服务端收到:" + message + "\r\n";
    ctx.writeAndFlush(response);
}
🎯 运行效果
  • 代码最简洁优雅
  • 收发数据都使用String类型
  • 不需要手动处理ByteBuf
📊 与项目1-04的对比
功能项目1-04项目1-05
编码方式手动编码内置编码器
代码复杂度高低
发送类型ByteBufString
💡 最佳实践
  • 优先使用Netty内置的编解码器
  • 保持代码简洁优雅
  • 关注业务逻辑,而不是底层细节

项目 1-06:实现群发消息功能

📌 项目目标

在1-05项目的基础上增加群发消息功能,引入ChannelGroup核心概念,实现群发消息功能。

🔑 核心知识点
  1. ChannelGroup:Channel组,用于管理多个Channel

    • 可以同时向多个Channel发送消息
    • 自动管理Channel的生命周期
  2. DefaultChannelGroup:ChannelGroup的默认实现

  3. 群发消息:向所有连接的客户端发送消息

💻 核心代码解析

ChannelHandler.java - 管理Channel组

public class ChannelHandler extends ChannelInboundHandlerAdapter {
    
    // 创建Channel组,用于管理所有连接的客户端
    private static ChannelGroup channelGroup = new DefaultChannelGroup(
        GlobalEventExecutor.INSTANCE
    );
    
}

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 连接激活时调用
     * 
     * ⭐ 核心变化:将新连接加入到ChannelGroup
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // ⭐ 第一步:将新连接的Channel加入到channelGroup(加入群聊)
        // 之后这个Channel就可以接收群发消息了
        ChannelHandler.channelGroup.add(ctx.channel());
        
        // 第二步:打印连接信息
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.out.println("链接报告开始");
        System.out.println("链接报告信息:有一客户端链接到本服务端");
        System.out.println("链接报告IP:" + channel.localAddress().getHostString());
        System.out.println("链接报告Port:" + channel.localAddress().getPort());
        System.out.println("链接报告完毕");
        System.out.println("当前在线人数:" + ChannelHandler.channelGroup.size());
        
        // 第三步:通知客户端连接成功
        String str = "通知客户端链接建立成功" + " " + new Date() + " " 
            + channel.localAddress().getHostString() + "\r\n";
        ctx.writeAndFlush(str);
    }

    /**
     * 连接断开时调用
     * 
     * ⭐ 核心变化:从ChannelGroup中移除断开的连接
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("客户端断开链接" + ctx.channel().localAddress().toString());
        
        // ⭐ 从channelGroup中移除(退出群聊)
        // 之后这个Channel就不会再收到群发消息了
        ChannelHandler.channelGroup.remove(ctx.channel());
        System.out.println("当前在线人数:" + ChannelHandler.channelGroup.size());
    }

    /**
     * 接收数据时调用
     * 
     * ⭐⭐⭐ 核心变化:群发消息给所有客户端
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 接收消息
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) 
            + " 接收到消息:" + msg);
        
        // ⭐⭐⭐ 核心功能:群发消息
        // 
        // 项目五(点对点):
        //   ctx.writeAndFlush(str);  // 只发给当前发送消息的客户端
        // 
        // 项目六(群发):
        //   ChannelHandler.channelGroup.writeAndFlush(str);  // 发给所有客户端
        // 
        // 效果:
        //   客户端A发送消息 → 服务端接收 → 群发给A、B、C所有客户端
        String str = "服务端收到:" + new Date() + " " + msg + "\r\n";
        ChannelHandler.channelGroup.writeAndFlush(str);
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        System.out.println("异常信息:\r\n" + cause.getMessage());
    }

}
🎯 运行效果
  • 启动多个客户端连接服务端
  • 任意客户端发送消息,所有客户端都能收到
  • 实现了简单的聊天室功能
📊 与项目1-05的对比
功能项目1-05项目1-06
发送方式单播(一对一)群发(一对多)
Channel管理无ChannelGroup
应用场景简单通信聊天室、推送
💡 应用场景
  • 聊天室:群发聊天消息
  • 消息推送:向所有在线用户推送通知
  • 游戏服务器:广播游戏状态

超详细Netty入门,看这篇就够了! 阅读详情

相关推荐

Netty学习笔记(一)

👍Netty的官网Netty 是由 JBOSS 提供的一个 java 开源框架,现为 Github 上的独立项目。Netty 提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty 是一个 NIO 客户端服务器框架,它支持协议服务器和客户端等网络应用程序的快速、简便开发。它极大地简化了网络编程,如 TCP 和 UDP 套接字服务器。

Roc的博客 883

Netty基础学习(一)

为什么要学习netty netty有哪些基础知识点 如何将netty日常工作结合起来 netty的高阶使用

西木风落 1916

Netty入门-Netty篇

Netty 是什么?、 EventLoop、 channel、 ChannelFuture、 sync 和 addListener 区别、 如何正确处理 客户端传输通道 channel 关闭以后的操作?、 优雅的结束进程、 Future & Promise、 jdk Future、 netty Future、 netty Promise、 Handler & Pipeline、 pipeline调试工具 EmbeddedChannel、 ByteBuf 读写操作、 调试 ByteBuf 的工具 log方法、

原名又逢乱世。不要放下学习的脚步,毕竟比天天打牌、钓鱼、打游戏更能从内在充实自己。 1901

Netty深入浅出Java网络编程学习笔记(一) Netty入门篇

本文介绍了Netty的基本概念和组件。Netty是一款Java网络编程框架,具有高性能和可扩展性。通过一个入门案例,我们了解了Netty的运行流程和组件的作用。其中包括EventLoop用于处理任务,Channel用于管理连接,Future与Promise用于处理异步操作,Handler与Pipeline用于实现数据的处理与传递,以及ByteBuf用于高效的内存操作。这些组件共同构成了Netty的核心,使其成为构建高性能网络应用程序的理想选择。

weixin_73077810的博客 1205

DDSP(Differentiable Digital Signal Processing) 开篇

文章目录DDSP可以用来做什么?下一步工作 工作中接触到了DDSP声码器,但非科班出声的我对这块知识非常陌生,甚至带有一些畏惧的心理,但是为了工作为了进步,必须硬下头皮去啃,相信只要耐心地坚持,没什么能难到我。于是从今天开始,就用这个博客专栏来记录我的学习历程,希望也能帮助到你~ DDSP对应的论文是:DDSP: Differentiable Digital Signal Processing 先翻译一篇来自DDSP论文作者的对DDSP的介绍的文章。 今天,我们很高兴地介绍可微数字信号处理(DDSP)库。

YeeKo的博客 9248

黑金AXU9EG开发板深度学习部署全流程解析

本文详细解析了黑金AXU9EG开发板的深度学习模型部署全流程,从环境搭建、模型转换到上板验证,提供了实用的技术指导和优化技巧。该开发板基于Xilinx Zynq UltraScale+ MPSoC架构,特别适合边缘计算场景,通过FPGA加速实现高效AI推理。

weixin_29062613的博客 448

netty权威指南学习笔记一——netty入门应用

  经过了前面的NIO基础知识准备,我们已经对NIO有了较大了解,现在就进入netty的实际应用中来看看吧。重点体会整个过程。 一、首先我们需要一个netty的环境,netty的环境搭建只需要一个netty的jar包即可。   在maven工程中导入netty的jar资源 1 &lt;!-- https://mvnrepository.com/artifact/io.n...

zuixiaoyao_001的博客 349

visual studio 2017编译Triangle库遇到的问题和解决办法

这段时间因为一个项目需要使用到Triangle这个三角剖分工具,需要在windows环境下进行对源码编译,中间踩了很多坑,特此记录下。 1、下载 下载链接是下边这个,需要翻墙 http://www.cs.cmu.edu/~quake/triangle.html 2、编译。。超。。。级。。。麻。。。烦。。。 在ubutu下安装一切顺利,完全没遇到什么麻烦,但是换到windows下就麻烦不断...

csubai07的博客 2440

Netty入门(快速了解以及使用netty)

Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端。Netty 在 Java 网络应用框架中的地位就好比:Spring 框架在 JavaEE 开发中的地位 以下的框架都使用了 Netty,因为它们有网络通信需求! Cassandra - nosql 数据库 Spark - 大数据分布式计算框架 Hadoop - 大数据分布式存储框架 RocketMQ - ali 开源的消息队列 ElasticSearch - 搜索引擎 gRPC

lonelykkk的博客 8629

Fluent基于低氧舱气体交换仿真(氮气与空气混合)

一、背景概述 模拟低氧舱充氮气和排除混合气体的过程,假设注入95%的氮气,舱内原有气体为空气,压力为标准大气压,温度为300K。观察气体注入过程中,舱内平均氮气和氧气浓度的变化。 二、Fluent设置 Setup 1、General type选择压力基 绝对速度 瞬态 重力勾选 2、Model 能量方程开启 组分运输开启,设置方法如下: 选择后OK,view就会变成Edit,点击Edit。然后再次点击Edit。 将组分中的非氮气氧气和空气的气体移除,右边选项需要将空气放在最后一位。 3、Materi

qq_35535616的博客 1万+

Python 爬虫实战:亚马逊 + eBay 商品信息跨平台抓取(价格 / 销量 / 评价对比)

亚马逊和 eBay 是全球知名的电商平台,拥有海量的商品信息。对于消费者来说,比较不同平台上的商品价格、销量和用户评价可以帮助他们找到性价比最高的商品。对于商家而言,了解竞争对手的商品信息有助于优化自身的产品策略和定价策略。然而,手动在两个平台上逐一比较商品信息是非常耗时且低效的。因此,开发一个能够自动抓取并对比这两个平台商品信息的爬虫工具具有重要的实际意义。

yansideyucsdn的博客 617

Netty学习笔记-Netty入门

EventLoopGroup 翻译:事件循环组,channel一般会调用EventLoopGroup的register的方法来绑定其中一个EventLoop,后续这个channel的io事件都由这个EventLoop 来处理(保证了io事件处理时的线程安全)负责根据一定的策略选择下一个可用的EventExecutor,通常是一个NioEventLoop。底层实现是两个不同的。的执行器,里面有run方法处理channel上源源不断的io事件。next()方法的实现逻辑主要是通过对内部维护的。

Ninomi_的博客 1310

【EB_Tresos专题】-01-EB Tresos导入工程

<--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--返回「个人博客」首页--> <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--返回「个人博客」首页--> 结尾 ...

「汽车电子助手」的博客 6437

Netty入门 -- 什么是Netty?

通俗易懂,一文让你搞懂Netty~

wanghuichen的博客 2331

couldn‘t upgrade db schema: insert into ACT_GE_PROPERTY values (‘common.sche[已解决]

启动整合了flowable的项目,初始化时报错。flowable没有自动建表, 原因 测试数据库版本是MySQL5.7。经过查询和尝试,原因是:在这个数据库里面,已经有一个数据库里面有activiti的这些表了,它检索的时候全库检索查到它了,所以flowable不去建表了,但是我们指定的这个schema里卖弄还是空的,所以它报了找不到表。解决方法:mysql的链接上加上参数如下,让本schema成为默认的schema。...

JavaPub 6021

windows中搭建sonic云真机环境/云真机环境搭建-基于docker容器部署

基于Windows系统搭建Sonic远程云真机环境实现通过浏览器操作手机端系统

雾林小妖的博客 1019

Netty入门

【零拷贝】的体现之一,对原始 ByteBuf 进行切片成多个 ByteBuf,切片后的 ByteBuf 并没有发生内存复制,还是使用原始 ByteBuf 的内存,切片后的 ByteBuf 维护独立的 read,write 指针。netty 中的 Future 与 jdk 中的 Future 同名,但是是两个接口,netty 的 Future 继承自 jdk 的 Future,而 Promise 又对 netty Future 进行了扩展。connect 方法是异步的,意味着不等连接建立,方法执行就返回了。

我的博客 1690

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Netty从入门到进阶(一)

本教程详细讲解了Netty和NIO的核心概念与技术要点。

ltt159264的博客 934

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Netty学习——Netty入门

二. Netty 入门 1. 概述 1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty 是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端。 这里的异步是指Netty采用了

maruofan666的博客 1985

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Netty入门(一)环境搭建及使用

本文介绍了使用Netty框架实现简单服务端程序的步骤:1. 在Eclipse中创建Maven项目并添加Netty依赖;2. 编写自定义消息处理器类HelloServerHandler,实现接收客户端消息并输出到控制台;3. 创建HelloServer类配置Netty服务器参数,包括线程组、通道初始化等;4. 使用telnet作为客户端进行测试,验证服务端能正确接收并显示客户端发送的消息。整个过程展示了Netty服务端的基本实现流程,从项目配置到代码编写再到功能测试。

ywl470812087的博客 16万+

超详细Netty入门

官方的介绍:Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。

2301_76406247的博客 3851

Netty 学习笔记

黑马程序员Netty全套教程 Channel 是读写数据的双向通道,Buffer是内存缓冲区,暂存数据。常见的 Channel 和 Buffer 见讲义。 ByteBuffer(包括MappedByteBuffer、DirectByteBuffer、HeapByteBuffer)最常用。多线程设计:多个客户端对应多个socket,就会启动多个线程。每个线程对应一个socket连接 缺点:内存占用高、线程上下文切换成本高、只适合连接数少的场景 线程池版设计,缺点:阻塞模式下,线程仅能处理一个 socket

cutlery1137的博客 784
上一篇: 网络编程基础:从BIO到NIO再到AIO(四)
下一篇: Netty入门学习笔记(二)
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值