当前位置:首页 » 《随便一记》 » 正文

【Java】Netty创建网络服务端客户端(TCP/UDP)

29 人参与  2024年04月14日 18:05  分类 : 《随便一记》  评论

点击全文阅读


?★,°:.☆( ̄▽ ̄)/$:.°★ ?
这篇文章主要介绍Netty创建网络服务端客户端示例。
学其所用,用其所学。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路?

文章目录

:smirk:1. Netty介绍:blush:2. 环境安装与配置:satisfied:3. TCP应用示例:satisfied:4. UDP应用示例

?1. Netty介绍

Netty官网:https://netty.io/

Netty是一个基于Java的异步事件驱动的网络应用程序框架,专门用于快速开发高性能、可扩展和可维护的网络服务器和客户端。它提供了简单而强大的API,使开发人员能够轻松地构建各种网络应用,包括TCP、UDP、HTTP、WebSocket等。

以下是一些关键特点和功能:

1.异步和事件驱动:Netty使用非阻塞I/O模型,通过异步事件驱动方式处理网络操作,提供了卓越的性能和可扩展性。

2.高性能:Netty通过有效地利用底层操作系统提供的机制(如选择器、零拷贝等)来实现高效的数据传输和处理,以满足对性能和吞吐量的要求。

3.安全:Netty提供了强大的加密和认证支持,包括SSL/TLS和各种认证机制,保护网络通信的安全性。

4.多协议支持:Netty支持多种主流的网络协议,如TCP、UDP、HTTP、WebSocket等,使开发人员可以方便地构建不同类型的网络应用。

5.灵活的处理程序模型:Netty采用了高度可扩展的处理程序(Handler)模型,使开发人员可以按需配置和组合处理程序来处理网络事件和数据,实现复杂的业务逻辑。

6.内置编解码器:Netty提供了丰富的内置编解码器,使开发人员能够轻松地处理各种协议和数据格式,简化了网络通信中的数据编解码工作。

7.完善的文档和社区支持:Netty拥有完善的官方文档、示例代码和教程,以及活跃的社区支持,使开发人员能够快速上手并解决问题。

?2. 环境安装与配置

IDEA创建Netty工程,只要在pom.xml中引入如下依赖:

    <dependencies>        <dependency>            <groupId>io.netty</groupId>            <artifactId>netty-all</artifactId>            <version>4.1.49.Final</version>        </dependency>    </dependencies>

?3. TCP应用示例

创建TCP服务端客户端,需要先开启通道Channel,然后再有一个事件处理Handler,下面就创建这4个类:

在这里插入图片描述

NettyServer.java

package org.example;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.logging.LogLevel;import io.netty.handler.logging.LoggingHandler;public class NettyServer {    private final int port;    public NettyServer(int port) {        this.port = port; // server port    }    public void start() throws Exception {        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            ServerBootstrap b = new ServerBootstrap();            b.group(bossGroup, workerGroup)                    .channel(NioServerSocketChannel.class)                    .option(ChannelOption.SO_BACKLOG, 128)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childHandler(new ChannelInitializer<SocketChannel>() {                        @Override                        public void initChannel(SocketChannel ch) throws Exception {                            ch.pipeline().addLast(new NettyServerHandler()); // channel to handler                        }                    });            ChannelFuture f = b.bind(port).sync();            System.out.println("Server started on port " + port);            f.channel().closeFuture().sync();        } finally {            workerGroup.shutdownGracefully();            bossGroup.shutdownGracefully();        }    }    public static void main(String[] args) throws Exception {        int port = 8080;        NettyServer server = new NettyServer(port);        server.start();    }}

NettyServerHandler.java

package org.example;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.*;import io.netty.util.CharsetUtil;public class NettyServerHandler extends ChannelInboundHandlerAdapter {    /**     * 读取数据实际(这里我们可以读取客户端发送的消息)     * @param ctx 上下文对象     * @param msg 客户端发送的数据     * @throws Exception     */    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        System.out.println("server ctx =" + ctx);        Channel channel = ctx.channel();        // 将 msg 转成一个 ByteBuf        // ByteBuf 是 Netty 提供的,不是 NIO 的 ByteBuffer.        ByteBuf buf = (ByteBuf) msg;        System.out.println("客户端发送的消息是: " + buf.toString(CharsetUtil.UTF_8));        System.out.println("客户端地址: " + channel.remoteAddress());    }    /**     * 读取完毕,回复     * @param ctx     * @throws Exception     */    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        // writeAndFlush 是 write + flush 将数据写入到缓存,并刷新        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Client!", CharsetUtil.UTF_8));    }    /**     * 处理异常, 一般是需要关闭通道     * @param ctx     * @param cause     * @throws Exception     */    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        ctx.close();    }}

NettyClient.java

package org.example;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;public class NettyClient {    private final String host;    private final int port;    public NettyClient(String host, int port) {        this.host = host; // ip        this.port = port; // port    }    public void start() throws Exception {        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 {                            ch.pipeline().addLast(new NettyClientHandler());                        }                    });            ChannelFuture f = b.connect(host, port).sync();            System.out.println("Connected to " + host + ":" + port);            f.channel().closeFuture().sync();        } finally {            group.shutdownGracefully();        }    }    public static void main(String[] args) throws Exception {        String host = "localhost";        int port = 8080;        NettyClient client = new NettyClient(host, port);        client.start();    }}

NettyClientHandler.java

package org.example;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.util.CharsetUtil;public class NettyClientHandler extends ChannelInboundHandlerAdapter {    /**     * 通道创建就绪后触发     * @param ctx     * @throws Exception     */    @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        System.out.println("client ctx =" + ctx);        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Server!", CharsetUtil.UTF_8));    }    /**     * 当通道有读取事件时,会触发     * @param ctx     * @param msg     * @throws Exception     */    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        ByteBuf buf = (ByteBuf) msg;        System.out.println("服务器回复的消息:" + buf.toString(CharsetUtil.UTF_8));        System.out.println("服务器的地址: "+ ctx.channel().remoteAddress());    }    /**     * 处理异常, 一般是需要关闭通道     * @param ctx     * @param cause     * @throws Exception     */    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

分别运行服务端和客户端类,结果如下:

在这里插入图片描述

?4. UDP应用示例

跟上面TCP类似,UDP也是要创建Channel和Handler,下面创建这4个类:

在这里插入图片描述

UDPServer.java

package org.example;import io.netty.bootstrap.Bootstrap;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.DatagramChannel;import io.netty.channel.socket.nio.NioDatagramChannel;public class UDPServer {    private final int port;    public UDPServer(int port) {        this.port = port;    }    public void start() throws Exception {        EventLoopGroup group = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(group)                    .channel(NioDatagramChannel.class)                    .handler(new ChannelInitializer<DatagramChannel>() {                        @Override                        protected void initChannel(DatagramChannel ch) throws Exception {                            ch.pipeline().addLast(new UDPServerHandler());                        }                    });            ChannelFuture f = b.bind(port).sync();            System.out.println("Server started on port " + port);            f.channel().closeFuture().sync();        } finally {            group.shutdownGracefully();        }    }    public static void main(String[] args) throws Exception {        int port = 8888;        UDPServer server = new UDPServer(port);        server.start();    }}

UDPServerHandler.java

package org.example;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.channel.socket.DatagramPacket;import io.netty.util.CharsetUtil;public class UDPServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {    @Override    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {        // 处理接收到的数据        String receivedMessage = msg.content().toString(CharsetUtil.UTF_8);        System.out.println("Received message: " + receivedMessage);        // 响应客户端        String responseMessage = "Hello, client!";        DatagramPacket responsePacket = new DatagramPacket(Unpooled.copiedBuffer(responseMessage, CharsetUtil.UTF_8),                msg.sender());        ctx.writeAndFlush(responsePacket);    }}

UDPClient.java

package org.example;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.Unpooled;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.DatagramChannel;import io.netty.channel.socket.DatagramPacket;import io.netty.channel.socket.nio.NioDatagramChannel;import io.netty.util.CharsetUtil;import java.net.InetSocketAddress;public class UDPClient {    private final String host;    private final int port;    public UDPClient(String host, int port) {        this.host = host;        this.port = port;    }    public void start() throws Exception {        EventLoopGroup group = new NioEventLoopGroup();        try {            Bootstrap b = new Bootstrap();            b.group(group)                    .channel(NioDatagramChannel.class)                    .handler(new ChannelInitializer<DatagramChannel>() {                        @Override                        protected void initChannel(DatagramChannel ch) throws Exception {                            ch.pipeline().addLast(new UDPClientHandler());                        }                    });            ChannelFuture f = b.bind(0).sync();            System.out.println("Client started");            // 发送消息给服务端            String message = "Hello, server!";            DatagramPacket packet = new DatagramPacket(Unpooled.copiedBuffer(message, CharsetUtil.UTF_8),                    new InetSocketAddress(host, port));            f.channel().writeAndFlush(packet).sync();            f.channel().closeFuture().sync();        } finally {            group.shutdownGracefully();        }    }    public static void main(String[] args) throws Exception {        String host = "localhost";        int port = 8888;        UDPClient client = new UDPClient(host, port);        client.start();    }}

UDPClientHandler.java

package org.example;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.channel.socket.DatagramPacket;import io.netty.util.CharsetUtil;public class UDPClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {    @Override    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {        // 处理接收到的数据        String receivedMessage = msg.content().toString(CharsetUtil.UTF_8);        System.out.println("Received response from server: " + receivedMessage);    }}

运行结果如下:

在这里插入图片描述

请添加图片描述

以上。


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/95306.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1