两万字详解!Netty经典32连问! 2

简介: 两万字详解!Netty经典32连问! 2

15. Netty 中的各种 Codec 是什么,它们的作用是什么?

Netty 中,Codec 是一种将二进制数据与 Java 对象之间进行编码和解码的组件。它们可以将数据从字节流解码为 Java 对象,也可以将 Java 对象编码为字节流进行传输。

以下是 Netty 中常用的 Codec

  • ByteToMessageCodec:将字节流解码为 Java 对象,同时也可以将 Java 对象编码为字节流。可以用于处理自定义协议的消息解析和封装。
  • MessageToByteEncoder:将 Java 对象编码为字节流。通常用于发送消息时将消息转换为二进制数据。
  • ByteToMessageDecoder:将字节流解码为 Java 对象。通常用于接收到数据后进行解码。
  • StringEncoder 和 StringDecoder:分别将字符串编码为字节流和将字节流解码为字符串。
  • LengthFieldPrepender 和 LengthFieldBasedFrameDecoder:用于处理 TCP 粘包和拆包问题。
  • ObjectDecoder和ObjectEncoder:将Java对象序列化为字节数据,并将字节数据反序列化为Java对象。

这些 Codec 组件可以通过组合使用来构建复杂的数据协议处理逻辑,以提高代码的可重用性和可维护性。

16. 什么是 Netty 的 BootStrap,它的作用是什么?

Netty的Bootstrap是一个用于启动和配置Netty客户端和服务器的工具类。它提供了一组简单易用的方法,使得创建和配置Netty应用程序变得更加容易。

Bootstrap类提供了一些方法,可以设置服务器或客户端的选项和属性,以及为ChannelPipeline配置handler,以处理传入或传出的数据。一旦完成配置,使用Bootstrap启动客户端或服务器。

Netty应用程序中,Bootstrap有两个主要作用:

  • 作为Netty服务器启动的入口点:通过Bootstrap启动一个Netty服务器,可以在指定的端口上监听传入的连接,并且可以设置服务器的选项和属性。
  • 作为Netty客户端启动的入口点:通过Bootstrap启动一个Netty客户端,可以连接到远程服务器,并且可以设置客户端的选项和属性。

17.Netty的IO模型是什么?与传统的BIO和NIO有什么不同?

NettyIO模型是基于事件驱动的NIO(Non-blocking IO)模型。在传统的BIO(Blocking IO)模型中,每个连接都需要一个独立的线程来处理读写事件,当连接数过多时,线程数量就会爆炸式增长,导致系统性能急剧下降。而在NIO模型中,一个线程可以同时处理多个连接的读写事件,大大降低了线程的数量和切换开销,提高了系统的并发性能和吞吐量。

与传统的NIO模型相比,NettyNIO模型有以下不同点:

  • Netty使用了Reactor模式,将IO事件分发给对应的Handler处理,使得应用程序可以更方便地处理网络事件。
  • Netty使用了多线程模型,将Handler的处理逻辑和IO线程分离,避免了IO线程被阻塞的情况。
  • Netty支持多种Channel类型,可以根据应用场景选择不同的Channel类型,如NIO、EPoll、OIO等。

18. 如何在Netty中实现TCP粘包/拆包的处理?

TCP传输过程中,由于TCP并不了解上层应用协议的消息边界,会将多个小消息组合成一个大消息,或者将一个大消息拆分成多个小消息发送。这种现象被称为TCP粘包/拆包问题 。在Netty中,可以通过以下几种方式来解决TCP粘包/拆包问题:

  • 消息定长 :将消息固定长度发送,例如每个消息都是固定的100字节。在接收端,根据固定长度对消息进行拆分。
// 编码器,将消息的长度固定为100字节
pipeline.addLast("frameEncoder", new LengthFieldPrepender(2));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,根据固定长度对消息进行拆分
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(100, 0, 2, 0, 2));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));
  • 消息分隔符 :将消息以特定的分隔符分隔开,例如以"\r\n"作为分隔符。在接收端,根据分隔符对消息进行拆分。
// 编码器,以"\r\n"作为消息分隔符
pipeline.addLast("frameEncoder", new DelimiterBasedFrameEncoder("\r\n"));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,根据"\r\n"对消息进行拆分
pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));
  • 消息头部加长度字段 :在消息的头部加上表示消息长度的字段,在发送端发送消息时先发送消息长度,再发送消息内容。在接收端,先读取消息头部的长度字段,再根据长度读取消息内容。
// 编码器,将消息的长度加入消息头部
pipeline.addLast("frameEncoder", new LengthFieldPrepender(2));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,先读取消息头部的长度字段,再根据长度读取消息内容
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 2, 0, 2));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));

19. Netty如何处理大文件的传输?

Netty中,可以通过使用ChunkedWriteHandler处理大文件的传输。ChunkedWriteHandler是一个编码器,可以将大文件切分成多个Chunk,并将它们以ChunkedData的形式写入管道,这样就可以避免一次性将整个文件读入内存,降低内存占用。

具体使用方法如下:

  • 在服务端和客户端的ChannelPipeline中添加ChunkedWriteHandler
pipeline.addLast(new ChunkedWriteHandler());
  • 在服务端和客户端的业务逻辑处理器中,接收并处理ChunkedData
public class MyServerHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            // 处理HTTP请求
            // ...
        } else if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;
            // 处理HTTP内容
            if (content instanceof LastHttpContent) {
                // 处理完整个HTTP请求
                // ...
            } else if (content instanceof HttpChunkedInput) {
                HttpChunkedInput chunkedInput = (HttpChunkedInput) content;
                // 处理ChunkedData
                while (true) {
                    HttpContent chunk = chunkedInput.readChunk(ctx.alloc());
                    if (chunk == null) {
                        break;
                    }
                    // 处理单个Chunk
                    // ...
                }
            }
        }
    }
}
  • 在客户端向服务端发送数据时,将需要传输的文件包装成ChunkedFile并写入管道。
public void sendFile(Channel channel, File file) throws Exception {
    RandomAccessFile raf = new RandomAccessFile(file, "r");
    DefaultFileRegion fileRegion = new DefaultFileRegion(raf.getChannel(), 0, raf.length());
    HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/");
    HttpUtil.setContentLength(request, raf.length());
    channel.write(request);
    channel.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, file.length(), 8192)));
}

在传输大文件时,还需要注意以下几点

  • 使用ChunkedFile时需要指定Chunk的大小,根据实际情况选择合适的大小,一般建议不要超过8KB
  • 为了避免大文件传输过程中对网络造成影响,可以在服务端和客户端的ChannelPipeline中添加WriteBufferWaterMark,限制写入缓冲区的大小。
pipeline.addLast(new WriteBufferWaterMark(8 * 1024, 32 * 1024));

20. 如何使用Netty实现心跳机制?

Netty中,可以通过实现一个定时任务来实现心跳机制。具体来说,就是在客户端和服务端之间定时互相发送心跳包,以检测连接是否仍然有效。

以下是使用Netty实现心跳机制的基本步骤

  • 定义心跳消息的类型。
public class HeartbeatMessage implements Serializable {
    // ...
}
  • 在客户端和服务端的ChannelPipeline中添加IdleStateHandler,用于触发定时任务。
pipeline.addLast(new IdleStateHandler(0, 0, 60, TimeUnit.SECONDS));
  • 在客户端和服务端的业务逻辑处理器中,重写userEventTriggered方法,在触发定时任务时发送心跳包。
public class MyServerHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                // 读空闲,发送心跳包
                ctx.writeAndFlush(new HeartbeatMessage());
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
  • 在客户端和服务端的业务逻辑处理器中,重写channelRead方法,接收并处理心跳包。
public class MyClientHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HeartbeatMessage) {
            // 收到心跳包,不做处理
            return;
        }
        // 处理其他消息
        // ...
    }
}

需要注意的是,由于心跳包不需要传输大量数据,因此建议使用Unpooled.EMPTY_BUFFER作为心跳包的内容。另外,心跳间隔的时间应根据实际情况设置,一般建议设置为连接的超时时间的一半。

21. Netty中如何实现SSL/TLS加密传输?

Netty 中实现 SSL/TLS 加密传输,需要通过 SSLHandler来进行处理。通常情况下,SSLHandler 需要在 ChannelPipeline 中作为最后一个handler添加。

以下是实现 SSL/TLS 加密传输的示例代码:

// 创建 SSLContext 对象,用于构建 SSLEngine
SSLContext sslContext = SSLContext.getInstance("TLS");
// 初始化 SSLContext
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("server.jks"), "password".toCharArray());
keyManagerFactory.init(keyStore, "password".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
// 获取 SSLEngine
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(false);
// 添加 SslHandler 到 ChannelPipeline 中
pipeline.addLast("ssl", new SslHandler(sslEngine));

22. NioEventLoopGroup 默认的构造函数会起多少线程?

默认情况下,NioEventLoopGroup 的构造函数会根据可用的处理器核心数 (availableProcessors()) 创建相应数量的线程。

具体来说,NioEventLoopGroup 的默认构造函数内部调用了另一个构造函数,其参数 nThreads 的默认值为 0,表示使用默认线程数。而默认线程数的计算方式就是调用 Runtime.getRuntime().availableProcessors() 方法获取当前机器可用的处理器核心数。

因此,如果你在一台四核的机器上创建了一个默认的 NioEventLoopGroup 实例,那么它就会使用四个线程。如果你想要修改线程数,可以调用 NioEventLoopGroup 的其他构造函数,并传入自定义的线程数。

23. 如何使用Netty实现WebSocket协议?

Netty 中实现 WebSocket 协议,需要使用 WebSocketServerProtocolHandler 进行处理。WebSocketServerProtocolHandler 是一个 ChannelHandler,可以将 HTTP 升级为 WebSocket 并处理 WebSocket 帧。

以下是实现 WebSocket 协议的示例代码:

// 添加 HTTP 请求解码器
pipeline.addLast("httpDecoder", new HttpRequestDecoder());
// 添加 HTTP 响应编码器
pipeline.addLast("httpEncoder", new HttpResponseEncoder());
// 添加 HTTP 聚合器
pipeline.addLast("httpAggregator", new HttpObjectAggregator(65536));
// 添加 WebSocket 服务器协议处理器
pipeline.addLast("webSocketHandler", new WebSocketServerProtocolHandler("/ws"));
// 添加自定义的 WebSocket 处理器
pipeline.addLast("handler", new MyWebSocketHandler());

在以上示例代码中,WebSocketServerProtocolHandler 的参数 "/ws" 表示 WebSocket 请求的 URL 路径,MyWebSocketHandler 是自定义的 WebSocket 处理器。

24. Netty 高性能表现在哪些方面?

  • 异步非阻塞 I/O 模型:Netty 使用基于NIO的异步非阻塞 I/O 模型,可以大大提高网络通信效率,减少线程的阻塞等待时间,从而提高应用程序的响应速度和吞吐量。
  • 零拷贝技术:Netty 支持零拷贝技术,可以避免数据在内核和用户空间之间的多次复制,减少了数据拷贝的次数,从而提高了数据传输的效率和性能。
  • 线程模型优化:Netty 的线程模型非常灵活,可以根据不同的业务场景选择不同的线程模型。例如,对于低延迟和高吞吐量的场景,可以选择 Reactor 线程模型,对于 I/O 操作比较简单的场景,可以选择单线程模型。
  • 内存池技术:Netty 提供了一套基于内存池技术的 ByteBuf 缓冲区,可以重用已经分配的内存空间,减少内存的分配和回收次数,提高内存使用效率。
  • 处理器链式调用:Netty ChannelHandler 可以按照一定的顺序组成一个处理器链,当事件发生时,会按照处理器链的顺序依次调用处理器,从而实现对事件的处理。这种处理方式比传统的多线程处理方式更加高效,减少了线程上下文切换和锁竞争等问题。

25. Netty 和 Tomcat 的区别?

Netty 和 Tomcat 都是 Java Web 应用服务器,但是它们之间存在一些区别:

  • 底层网络通信模型不同:Tomcat 是基于阻塞的 BIO(Blocking I/O)模型实现的,而 Netty 是基于 NIO(Non-Blocking I/O)模型实现的。
  • 线程模型不同:Tomcat 使用传统的多线程模型,每个请求都会分配一个线程,而 Netty 使用 EventLoop 线程模型,每个 EventLoop 负责处理多个连接,通过线程池管理 EventLoop
  • 协议支持不同:Tomcat 内置支持 HTTP 和 HTTPS 协议,而 Netty 不仅支持 HTTP 和 HTTPS 协议,还支持 TCP、UDP 和 WebSocket 等多种协议。
  • 代码复杂度不同:由于Tomcat支持的功能比较全面,所以其代码相对较为复杂,而 Netty 的代码相对比较简洁、精简。
  • 应用场景不同:Tomcat 适合于处理比较传统的 Web 应用程序,如传统的 MVC 模式Web应用程序;而 Netty 更适合于高性能、低延迟的网络应用程序,如游戏服务器、即时通讯服务器等。

26. 服务端Netty的工作架构图

             ┌───────┐        ┌───────┐
             │ Channel │◀───────│ Socket│
             │Pipeline │        │       │
             └───────┘        └───────┘
                   ▲                 │
                   │                 │
         ┌─────────┴─────────┐       │
         │                   │       │
         ▼                   ▼       ▼
┌──────────────┐   ┌──────────────┐  ┌──────────────┐
│EventLoopGroup│   │EventLoopGroup│  │EventLoopGroup│
│       boss   │   │     work     │  │     work     │
└──────────────┘   └──────────────┘  └──────────────┘
         ▲                   ▲       ▲
         │                   │       │
┌────────┴─────────┐ ┌────────┴─────────┐
│     NioServerSocketChannel   │   NioSocketChannel      │ ...

整个服务端 Netty 的工作架构图包括了以下几个部分:

  • ChannelPipeline:管道处理器,用于处理入站或出站事件,对数据进行编解码、处理业务逻辑等。
  • Channel:通道,对应底层的 Socket 连接,用于收发网络数据。
  • EventLoopGroup:事件循环组,包含了多个事件循环(EventLoop),每个事件循环负责处理多个通道上的事件。
  • EventLoop:事件循环,负责监听注册到该循环的多个通道上的事件,然后根据事件类型将事件派发给对应的处理器。
  • NioServerSocketChannel:NIO 服务端通道,用于接受客户端的连接。
  • NioSocketChannel:NIO 客户端通道,用于和服务端进行数据通信。

在服务端启动时,会创建一个或多个 EventLoopGroup。其中一个 EventLoopGroup 作为boss线程池,用于接受客户端的连接请求,并将连接请求分发给work线程池中的某个 EventLoopwork 线程池中的EventLoop负责处理已经连接的客户端的数据通信。每个 EventLoop 负责处理一个或多个 NioSocketChannel,并维护该通道的事件队列,当事件发生时,将事件添加到事件队列中,并将事件派发到管道处理器中进行处理。

27. 简单聊聊:Netty的线程模型的三种使用方式?

Netty的线程模型有三种使用方式,分别是单线程模型、多线程模型和主从多线程模型。

  • 单线程模型 :所有的I/O操作都由同一个线程来执行。虽然这种方式并不适合高并发的场景,但是它具有简单、快速的优点,适用于处理I/O操作非常快速的场景,例如传输小文件等。
  • 多线程模 型:所有的I/O操作都由一组线程来执行,其中一个线程负责监听客户端的连接请求,其他线程负责处理I/O操作。这种方式可以支持高并发,但是线程上下文切换的开销较大,适用于处理I/O操作较为耗时的场景。
  • 主从多线程模型 :所有的I/O操作都由一组NIO线程来执行,其中一个主线程负责监听客户端的连接请求,其他从线程负责处理I/O操作。这种方式将接受连接和处理I/O操作分开,避免了线程上下文切换的开销,同时又能支持高并发,适用于处理I/O操作耗时较长的场景。

28. Netty 是如何保持长连接的

  • 心跳机制 :使用心跳机制可以定期向服务器发送一个简短的数据包,以保持连接处于活动状态。如果在一段时间内没有收到心跳包,就可以认为连接已经断开,从而及时重新建立连接。Netty提供了IdleStateHandler处理器,可以方便地实现心跳机制。
  • 断线重连机制 :在网络不稳定的情况下,连接可能会不可避免地断开。为了避免因为网络异常导致应用程序不能正常工作,可以实现断线重连机制,定期检查连接状态,并在连接断开时尝试重新连接。Netty提供了ChannelFutureListener接口和ChannelFuture对象,可以方便地实现断线重连机制。
  • 基于HTTP/1.1协议的长连接HTTP/1.1协议支持长连接,可以在一个TCP连接上多次发送请求和响应。在Netty中,可以使用HttpClientCodec和HttpObjectAggregator处理器,实现基于HTTP/1.1协议的长连接。
  • WebSocket协议WebSocket协议也支持长连接,可以在一个TCP连接上双向通信,实现实时数据交换。在Netty中,可以使用WebSocketServerProtocolHandlerWebSocketClientProtocolHandler处理器,实现WebSocket协议的长连接。

29. Netty 发送消息有几种方式?

Netty 中,发送消息主要有以下三种方式:

  • Channel.write(Object msg) :通过 Channel 写入消息,消息会被缓存到 Channel 的发送缓冲区中,等待下一次调用 flush() 将消息发送出去。
  • ChannelHandlerContext.write(Object msg) :通过 ChannelHandlerContext 写入消息,与 Channel.write(Object msg) 相比,ChannelHandlerContext.write(Object msg) 会将消息写入到 ChannelHandlerContext 的发送缓冲区中,等待下一次调用 flush() 将消息发送出去。
  • ChannelHandlerContext.writeAndFlush(Object msg) :通过 ChannelHandlerContext 写入并发送消息,等同于连续调用 ChannelHandlerContext.write(Object msg) ChannelHandlerContext.flush()

在使用上述三种方式发送消息时,需要注意到写操作可能会失败或被延迟,因此需要在发送消息时进行一定的错误处理或者设置超时时间。另外,也可以使用 Netty 提供的 ChannelFuture 对象来监听操作结果或者进行异步操作。

30. Netty 支持哪些心跳类型设置?

Netty 中,可以通过以下几种方式实现心跳机制:

  • IdleStateHandlerNetty 内置的空闲状态检测处理器,支持多种空闲状态检测(如读空闲、写空闲、读写空闲)。
  • 自定义心跳检测机制 :可以通过自定义实现 ChannelInboundHandler 接口的处理器来实现心跳检测,例如可以通过计时器或者线程来定期发送心跳包,或者通过对远程端口的连接状态进行检测等方式实现。
  • 使用心跳应答 :在应用层面定义心跳请求和应答消息,通过 ChannelInboundHandler 处理器监听接收到的心跳请求消息,并返回心跳应答消息,来实现心跳检测。如果一段时间内未收到对方的心跳应答消息,则认为连接已经失效。

需要注意的是,为了避免因心跳机制导致的网络负载过大或者频繁的连接断开和重连,应该根据具体业务场景选择适合的心跳类型和频率。

31. Netty的内存管理机制是什么?

Netty 的内存管理机制主要是通过 ByteBuf 类实现的。ByteBufNetty 自己实现的一个可扩展的字节缓冲区类,它在 JDKByteBuffer 的基础上做了很多优化和改进。

Netty ByteBuf 的内存管理主要分为两种方式:

  • 堆内存:ByteBuf 以普通的字节数组为基础,在 JVM 堆上分配内存。这种方式适用于小型数据的传输,如传输的是文本、XML 等数据。
  • 直接内存:ByteBuf 使用操作系统的堆外内存,由操作系统分配和回收内存。这种方式适用于大型数据的传输,如传输的是音视频、大型图片等数据。

对于堆内存,Netty 采用了类似于JVM 的分代内存管理机制,将缓冲区分为三种类型:堆缓冲区、直接缓冲区、复合缓冲区 。Netty 会根据不同的使用场景和内存需求来决定使用哪种类型的缓冲区,从而提高内存利用率。

在使用 ByteBuf 时,Netty 还实现了一些优化和特殊处理,如池化缓冲区、零拷贝等技术,以提高内存的利用率和性能的表现。

32. Netty 中如何实现高可用和负载均衡?

Netty本身并没有提供高可用和负载均衡的功能,但可以结合其他技术来实现这些功能。下面介绍一些常用的方案:

  • 高可用:通过在多台服务器上部署同一个应用程序实现高可用。可以使用负载均衡器来将请求分配给不同的服务器,当某台服务器出现故障时,负载均衡器可以将请求转发给其他可用的服务器。常用的负载均衡器包括Nginx、HAProxy等。
  • 负载均衡:负载均衡是将请求分配给多台服务器的过程,常用的负载均衡算法包括轮询、随机、权重 等。在Netty中可以使用多个EventLoop来处理请求,将请求分配给不同的EventLoop,从而实现负载均衡。另外,可以使用第三方框架,如Zookeeper、Consul等,来实现服务注册、发现和负载均衡。
  • 高可用与负载均衡的结合:可以使用多台服务器来实现高可用和负载均衡。在每台服务器上部署同一个应用程序,并使用负载均衡器来分配请求。当某台服务器出现故障时,负载均衡器可以将请求转发给其他可用的服务器,从而保证高可用和负载均衡。


相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
3天前
|
消息中间件 存储 网络协议
拼多多面试:Netty如何解决粘包问题?
粘包和拆包问题也叫做粘包和半包问题,**它是指在数据传输时,接收方未能正常读取到一条完整数据的情况(只读取了部分数据,或多读取到了另一条数据的情况)就叫做粘包或拆包问题。** 从严格意义上来说,粘包问题和拆包问题属于两个不同的问题,接下来我们分别来看。 ## 1.粘包问题 粘包问题是指在网络通信中,发送方连续发送的多个小数据包被接收方一次性接收的现象。这可能是因为底层传输层协议(如 TCP)会将多个小数据包合并成一个大的数据块进行传输,导致接收方在接收数据时一次性接收了多个数据包,造成粘连。 例如以下案例,正常情况下客户端发送了两条消息,分别为“ABC”和“DEF”,那么接收端也应该收到两
拼多多面试:Netty如何解决粘包问题?
|
22天前
|
存储 算法 Java
耗时3天写完的HashMap万字解析,争取一篇文章讲透它,面试官看了都直点头!
耗时3天写完的HashMap万字解析,争取一篇文章讲透它,面试官看了都直点头!
53 3
|
9月前
|
弹性计算 Java Unix
搭稳Netty开发的地基,用漫画帮你分清同步异步阻塞非阻塞
Netty Netty是一款非常优秀的网络编程框架,是对NIO的二次封装,本文将重点剖析Netty客户端的启动流程,深入底层了解如何使用NIO编程客户端。 Linux网络编程5种IO模型 根据UNIX网络编程对于IO模型的分类,UNIX提供了5种IO模型,分别是 阻塞IO 、 非阻塞IO、 IO复用 、 信号驱动IO 、 异步IO 。这几种IO模型在《UNIX网络编程》中有详解,这里作者只简单介绍,帮助大家回忆一下这几种模型。 对于Linux来说,所有的操作都是基于文件的,也就是我们非常熟悉的fd,在缺省的情况下,基于文件的操作都是 阻塞的 。下面就通过系统调用 recvfrom 来回顾下
69 0
|
22天前
|
分布式计算 前端开发 网络协议
13W字!腾讯高工手写“Netty速成手册”,3天能走向实战
在java界,netty无疑是开发网络应用的拿手菜。你不需要太多关注复杂的nio模型和底层网络的细节,使用其丰富的接口,可以很容易的实现复杂的通讯功能。
|
消息中间件 网络协议 JavaScript
两万字详解!Netty经典32连问!
两万字详解!Netty经典32连问!
|
消息中间件 缓存 网络协议
【Netty 从成神到升仙系列 大结局】全网一图流死磕解析 Netty 源码
【Netty 从成神到升仙系列 大结局】全网一图流死磕解析 Netty 源码
【Netty 从成神到升仙系列 大结局】全网一图流死磕解析 Netty 源码
|
监控 Java Linux
【Netty 从成神到升仙系列 二】你真的懂 NIOEventLoop 嘛?
【Netty 从成神到升仙系列 二】你真的懂 NIOEventLoop 嘛?
【Netty 从成神到升仙系列 二】你真的懂 NIOEventLoop 嘛?
|
存储 安全 Java
Java多线程基础——两万字详解
进程简单来说就是正在运行的程序,是可以通过双击执行的.exe文件,打开我们电脑的任务管理器,可以看到我们的电脑正在执行的进程,目前我们的电脑都是多进程模式。
102 0
Java多线程基础——两万字详解
|
存储 消息中间件 缓存
四万字爆肝总结java多线程所有知识点(史上最全总结)
全文从多线程的实现方式、线程的状态、线程的方法、线程的同步、线程的通讯、等角度对多线程的基础知识进行总结
394 1
四万字爆肝总结java多线程所有知识点(史上最全总结)
|
存储 网络协议 安全
[ 数据通信面试篇 ] 数通面试题大集合(详解),看完直怼面试官(一)(下)
面试网络方向的岗位,数通知识尤为重要。 这里我总结了200来个面试题,本文讲解前30个面试题。 这些问题搞懂了,什么技术支持工程师呀,远程技术支持工程师,网络工程师呀基本上没什么问题了。 当然了,也不只这些岗位会问道这些题,这里只罗列出来了契合的岗位。
550 1

热门文章

最新文章