netty基本概念及入门示例代码

一、定义

netty是一款异步事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端。

二、netty特征

  • 设计:统一的 API,支持多种传输类型,阻塞的和非阻塞的,简单而强大的线程模型,真正的无连接数据报套接字,支持链接逻辑组件以支持复用
  • 易用性:翔实的 Javadoc 和大量的示例集
  • 性能:拥有比 Java 的核心 API 更高的吞吐量以及更低的延迟,得益于池化和复用,拥有更低的资源消耗
    最少的内存复制
  • 健壮性:不会因为慢速、快速或者超载的连接而导致OutOfMemoryError,消除在高速网络中 NIO 应用程序常见的不公平读/写比率
  • 安全性:完整的 SSL/TLS 以及 StartTLS 支持
  • 社区驱动:发布快速而且频繁

三、netty的核心组件

  • 1、channel:channel是NIO的一个基本构造,可以看作是入站和出站的数据载体。它可以被打卡或者关闭,连接或者断开连接

  • 回调:回调其实就是一个方法,当一个回调被触发时,相关的事件可以被一个channelHandler处理。下面展示的时当一个连接被建立的时候,channeActive()方法被调用,并打印一条消息。

    public class ConnectHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelActive(ChannelHandlerContext ctx)
            throws Exception {   
            //  当一个新的连接已经被建立时,将会被调用
            // channelActive(ChannelHandlerContext)
            System.out.println(
                "Client " + ctx.channel().remoteAddress() + " connected");
        }
    }
    
  • 2、future:提供了另一种在操作完成时通知应用程序的方式,这个对象可以看作时一个异步操作的结果占位符;它将在未来的某个时刻完成。并提供对其结果的访问。

netty实现了其自身的ChannelFuture ,并且提供了额外的方法,这些方法使得我们能够注册一个或者多个ChannelFutureListener实例。

ublic interface ChannelFuture extends Future<Void> {

    /**
     * Returns a channel where the I/O operation associated with this
     * future takes place.
     */
    Channel channel();

    @Override
    ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> listener);

    @Override
    ChannelFuture addListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);

    @Override
    ChannelFuture removeListener(GenericFutureListener<? extends Future<? super Void>> listener);

    @Override
    ChannelFuture removeListeners(GenericFutureListener<? extends Future<? super Void>>... listeners);

    @Override
    ChannelFuture sync() throws InterruptedException;

    @Override
    ChannelFuture syncUninterruptibly();

    @Override
    ChannelFuture await() throws InterruptedException;

    @Override
    ChannelFuture awaitUninterruptibly();

    /**
     * Returns {@code true} if this {@link ChannelFuture} is a void future and so not allow to call any of the
     * following methods:
     * <ul>
     *     <li>{@link #addListener(GenericFutureListener)}</li>
     *     <li>{@link #addListeners(GenericFutureListener[])}</li>
     *     <li>{@link #await()}</li>
     *     <li>{@link #await(long, TimeUnit)} ()}</li>
     *     <li>{@link #await(long)} ()}</li>
     *     <li>{@link #awaitUninterruptibly()}</li>
     *     <li>{@link #sync()}</li>
     *     <li>{@link #syncUninterruptibly()}</li>
     * </ul>
     */
    boolean isVoid();
}

回调的示例代码:

Channel channel = ...;
// Does not block
ChannelFuture future = channel.connect( // 异步地连接到远程节点
    new InetSocketAddress("192.168.0.1", 25));
future.addListener(new ChannelFutureListener() {   //  注册一个 ChannelFutureListener,以便在操作完成时获得通知
    @Override
    public void operationComplete(ChannelFuture future) { //  ❶ 检查操作
的状态
       if (future.isSuccess()){ 
            ByteBuf buffer = Unpooled.copiedBuffer(  // 如果操作是成功的,则创建一个 ByteBuf 以持有数据
               "Hello",Charset.defaultCharset());
           ChannelFuture wf = future.channel()
                .writeAndFlush(buffer);  // 将数据异步地发送到远程节点。
返回一个 ChannelFuture
            ....
        } else {
            Throwable cause = future.cause(); //如果发生错误,则访问描述原因的 Throwable
            cause.printStackTrace();
        }
    }
});

3、事件和ChannelHanlder

Netty 使用不同的事件来通知我们状态的改变或者是操作的状态。这使得我们能够基于已经发生的事件来触发适当的动作。这些动作可能是:

  • 记录日志;
  • 数据转换;
  • 流控制;
  • 应用程序逻辑。

Netty 是一个网络编程框架,所以事件是按照它们与入站或出站数据流的相关性进行分类的。可能由入站数据或者相关的状态更改而触发的事件包括:

  • 连接已被激活或者连接失活;
  • 数据读取;
  • 用户事件;
  • 错误事件。

出站事件是未来将会触发的某个动作的操作结果,这些动作包括:

  • 打开或者关闭到远程节点的连接;
  • 将数据写到或者冲刷到套接字。

每个事件都可以被分发给ChannelHandler类中的某个用户实现的方法。这是一个很好的将事件驱动范式直接转换为应用程序构件块的例子

Netty 使用不同的事件来通知我们状态的改变或者是操作的状态。这使得我们能够基于已经发生的事件来触发适当的动作。这些动作可能是:

  • 记录日志;
  • 数据转换;
  • 流控制;
  • 应用程序逻辑。

Netty 是一个网络编程框架,所以事件是按照它们与入站或出站数据流的相关性进行分类的。可能由入站数据或者相关的状态更改而触发的事件包括:

  • 连接已被激活或者连接失活;
  • 数据读取;
  • 用户事件;
  • 错误事件。

出站事件是未来将会触发的某个动作的操作结果,这些动作包括:

  • 打开或者关闭到远程节点的连接;
  • 将数据写到或者冲刷到套接字。

每个事件都可以被分发给ChannelHandler类中的某个用户实现的方法。这是一个很好的将事件驱动范式直接转换为应用程序构件块的例子
在这里插入图片描述

四、示例代码

这里使用netty的源码的echo作为示例,添加了在控制输出的语句:

服务端代码:

cn.szyrm.network.nio.echo.EchoServer

/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package cn.szyrm.network.nio.echo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;

/**
 * Echoes back any received data from a client.
 */
public final class EchoServer {

    static final boolean SSL = System.getProperty("ssl") != null;
    static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));

    public static void main(String[] args) throws Exception {
        // Configure SSL.   
        final SslContext sslCtx;
        if (SSL) {
            SelfSignedCertificate ssc = new SelfSignedCertificate();
            sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
        } else {
            sslCtx = null;
        }

        // Configure the server.
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        final EchoServerHandler serverHandler = new EchoServerHandler();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .option(ChannelOption.SO_BACKLOG, 100)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     if (sslCtx != null) {
                         p.addLast(sslCtx.newHandler(ch.alloc()));
                     }
                     //p.addLast(new LoggingHandler(LogLevel.INFO));
                     p.addLast(serverHandler);
                 }
             });

            // Start the server.
            ChannelFuture f = b.bind(PORT).sync();

            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down all event loops to terminate all threads.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

服务端的自定义的handler

/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package cn.szyrm.network.nio.echo;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * Handler implementation for the echo server.
 */
@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
        if(msg instanceof ByteBuf){
          ByteBuf byteBuf =   (ByteBuf) msg;
            int i = byteBuf.readableBytes();
           byte[] bytes =  new byte[i];
           byteBuf.getBytes(0,bytes);
            System.out.println(new String(bytes));

        }


    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

客户端启动类:

/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package cn.szyrm.network.nio.echo;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;

/**
 * Sends one message when a connection is open and echoes back any received
 * data to the server.  Simply put, the echo client initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public final class EchoClient {

    static final boolean SSL = System.getProperty("ssl") != null;
    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
    static final int SIZE = Integer.parseInt(System.getProperty("size", "26"));

    public static void main(String[] args) throws Exception {
        // Configure SSL.git
        final SslContext sslCtx;
        if (SSL) {
            sslCtx = SslContextBuilder.forClient()
                .trustManager(InsecureTrustManagerFactory.INSTANCE).build();
        } else {
            sslCtx = null;
        }

        // Configure the client.
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .option(ChannelOption.TCP_NODELAY, true)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     if (sslCtx != null) {
                         p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT));
                     }
                     //p.addLast(new LoggingHandler(LogLevel.INFO));
                     p.addLast(new EchoClientHandler());
                 }
             });

            // Start the client.
            ChannelFuture f = b.connect(HOST, PORT).sync();

            // Wait until the connection is closed.
            f.channel().closeFuture().sync();
        } finally {
            // Shut down the event loop to terminate all threads.
            group.shutdownGracefully();
        }
    }
}

客户端handler方法:

/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package cn.szyrm.network.nio.echo;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * Handler implementation for the echo client.  It initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public class EchoClientHandler extends ChannelInboundHandlerAdapter {

    private final ByteBuf firstMessage;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler() {
        firstMessage = Unpooled.buffer(EchoClient.SIZE);
        for (int i = 65; i < firstMessage.capacity() + 65; i ++) {
            firstMessage.writeByte((byte) i);
        }
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
        if(msg instanceof ByteBuf){
            ByteBuf byteBuf =   (ByteBuf) msg;
            int i = byteBuf.readableBytes();
            byte[] bytes =  new byte[i];
            byteBuf.getBytes(0,bytes);
            System.out.println(new String(bytes));

        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
       ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 下面是使用 Netty 实现 WebSocket 图片传输的示例代码。需要注意的是,这个示例代码只是提供一个思路,具体的实现细节可能会有所不同。 首先,在服务端,你需要创建一个 ChannelInboundHandler 来处理来自客户端的 WebSocket 消息。在这个 handler 中,你可以检查消息的类型,如果是二进制消息,就读取它并将图片解码为 BufferedImage 对象。然后,你可以将图片存储在服务端或者将它转发给其他客户端。 ``` public class ImageHandler extends SimpleChannelInboundHandler<BinaryWebSocketFrame> { @Override protected void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame frame) throws Exception { // 读取二进制消息并解码为图片 BufferedImage image = ImageIO.read(new ByteArrayInputStream(frame.content().array())); // 处理图片,例如存储或转发 ... } } ``` 然后,在客户端,你需要创建一个 ChannelOutboundHandler 来处理要发送给服务端的 WebSocket 消息。在这个 handler 中,你可以将图片编码为二进制数据并发送给服务端。 ``` public class ImageSender extends ChannelOutboundHandlerAdapter { public void sendImage(ChannelHandlerContext ctx, BufferedImage image) { // 将图片编码为二进制数据 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "png", baos); byte[] data = baos.toByteArray(); // 发送二进制消息 ctx.writeAndFlush(new BinaryWebSocketFrame(Unpooled.wrappedBuffer ### 回答2: 以下是一个使用Netty进行WebSocket传输图片的示例代码: 服务器端代码: ``` import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.stream.ChunkedWriteHandler; public class WebSocketServer { public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline() .addLast(new HttpServerCodec()) .addLast(new HttpObjectAggregator(65536)) .addLast(new ChunkedWriteHandler()) .addLast(new WebSocketServerProtocolHandler("/websocket")) .addLast(new ImageWebSocketServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture future = bootstrap.bind(8080).sync(); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } ``` 服务器端使用了Netty的WebSocket协议处理器`WebSocketServerProtocolHandler`来支持WebSocket连接,并且根据自定义的图片处理器`ImageWebSocketServerHandler`处理接收到的图片数据。 客户端代码: ``` import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseDecoder; import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler; public class WebSocketClient { public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline() .addLast(new HttpResponseDecoder()) .addLast(new HttpRequestEncoder()) .addLast(new HttpObjectAggregator(65536)) .addLast(new WebSocketClientProtocolHandler("/websocket")) .addLast(new ImageWebSocketClientHandler()); } }) .option(ChannelOption.SO_KEEPALIVE, true); ChannelFuture future = bootstrap.connect("localhost", 8080).sync(); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } } ``` 客户端代码中,同样使用了Netty的WebSocket协议处理器`WebSocketClientProtocolHandler`来支持WebSocket连接,并且根据自定义的图片处理器`ImageWebSocketClientHandler`处理接收到的图片数据。 通过服务器端和客户端的组合使用,可以实现基于Netty的WebSocket传输图片的功能。 ### 回答3: Netty是一种基于Java的网络编程框架,它提供了一种简单而高效的方式来实现网络通信。WebSocket是一种在Web应用程序中实现双向通信的协议。使用Netty实现WebSocket传输图片的示例代码如下: 1.首先,需要添加Netty和WebSocket的依赖到项目中: ```xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.63.Final</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-transport-native-epoll</artifactId> <version>4.1.63.Final</version> <classifier>linux-x86_64</classifier> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-codec-http</artifactId> <version>4.1.63.Final</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-handler</artifactId> <version>4.1.63.Final</version> </dependency> ``` 2.创建一个WebSocket服务器类,用于处理WebSocket请求: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.handler.stream.ChunkedNioFile; import io.netty.handler.stream.ChunkedWriteHandler; public class WebSocketServer { public void run(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast("http-codec", new HttpServerCodec()); ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536)); ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler()); ch.pipeline().addLast("handler", new WebSocketServerHandler()); } }); ChannelFuture future = bootstrap.bind(port).sync(); System.out.println("WebSocket server started on port " + port); future.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new WebSocketServer().run(8080); } } ``` 3.创建一个WebSocket处理器,用于处理WebSocket请求并传输图片: ```java import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpClientCodec; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; public class WebSocketServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { private WebSocketServerHandshaker handshaker; @Override public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { if (!msg.decoderResult().isSuccess()) { sendHttpResponse(ctx, msg, HttpResponseStatus.BAD_REQUEST); return; } if ("/ws".equals(msg.uri())) { WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory("ws://localhost:8080/ws", null, false); handshaker = wsFactory.newHandshaker(msg); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); } else { handshaker.handshake(ctx.channel(), req); } } else { // 处理静态资源请求 // ... } } private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, HttpResponseStatus status) { ByteBuf content = Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8); FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, content); response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8"); ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } ``` 这段代码创建了一个基于Netty的WebSocket服务器,实现了WebSocket请求处理和图片传输的功能。具体步骤如下: 1.创建一个WebSocket服务器类,使用Netty的`ServerBootstrap`配置服务器,并在`initChannel`方法中添加必要的处理器。 2.在WebSocket服务器类中创建一个`WebSocketServerHandler`类,继承自Netty的`SimpleChannelInboundHandler<FullHttpRequest>`,用于处理WebSocket请求。 3.在`channelRead0`方法中,判断传入的请求是否为WebSocket握手请求,并进行相应处理。 4.如果是WebSocket握手请求,则通过`WebSocketServerHandshakerFactory`创建一个握手器,并进行握手。 5.如果不是WebSocket握手请求,则根据需要处理静态资源请求等。 6.在`sendHttpResponse`方法中,通过`FullHttpResponse`返回相关响应信息。 7.最后,在`main`方法中创建一个新的`WebSocketServer`对象并运行。 以上是一个简单的Netty WebSocket传输图片的示例代码,用于实现图片的传输和处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值