当前位置: 首页 > news >正文

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

😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍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>() {@Overridepublic 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*/@Overridepublic 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*/@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {// writeAndFlush 是 write + flush 将数据写入到缓存,并刷新ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Client!", CharsetUtil.UTF_8));}/*** 处理异常, 一般是需要关闭通道* @param ctx* @param cause* @throws Exception*/@Overridepublic 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; // ipthis.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>() {@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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>() {@Overrideprotected 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> {@Overrideprotected 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>() {@Overrideprotected 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> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {// 处理接收到的数据String receivedMessage = msg.content().toString(CharsetUtil.UTF_8);System.out.println("Received response from server: " + receivedMessage);}
}

运行结果如下:

在这里插入图片描述

请添加图片描述

以上。

相关文章:

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

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

Android 设计模式--单例模式

一&#xff0c;定义 单例模式就是确保某一个类只有一个实例&#xff0c;而且自行实例化&#xff0c;并向整个系统提供这个实例 二&#xff0c;使用场景 确保某个类只有一个对象的使用场景&#xff0c;避免产生多个对象消耗过多的资源&#xff0c;或者某种类型的对象只应该有…...

语音识别与自然语言处理(NLP):技术前沿与未来趋势

语音识别与自然语言处理&#xff08;NLP&#xff09;&#xff1a;技术前沿与未来趋势 随着科技的快速发展&#xff0c;语音识别与自然语言处理&#xff08;NLP&#xff09;技术逐渐成为人工智能领域的研究热点。这两项技术的结合&#xff0c;使得机器能够更好地理解和处理人类语…...

k8s-docker二进制(1.28)的搭建

二进制文件-docker方式 1、准备的服务器 角色ip组件k8s-master1192.168.11.111kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-master2192.168.11.112kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-node1192.168.11.113kubelet,kube-prox…...

【代码随想录】算法训练计划18

1、513. 找树左下角的值 题目&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 思路&#xff1a; 递归&#xff0c;规则&#xff0c;基本可以自己写出来 var maxDepth int var res int fun…...

Leetcode刷题详解—— 组合总和

1. 题目链接&#xff1a;39. 组合总和 2. 题目描述&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些…...

Echarts柱状体实现滚动条动态滚动

当我们柱状图中X轴数据太多的时候&#xff0c;会自动把柱形的宽度挤的很细&#xff0c;带来的交互非常不好&#xff0c;因此就有一个属性来解决&#xff1a;dataZoom 第一种简易的版本&#xff0c;横向滚动。 dataZoom: {show: true, // 为true 滚动条出现realtime: true, // 实…...

SplayTree高分测试用例

测试用例结果展示 覆盖率 变异得分 测试注意点 从SplayTree测起&#xff0c;然后再测SubSplayTree&#xff0c;因为前者调用后者。SplaySubTree的remove方法大部分内容需要通过反射才能测到。value和index在SplayTree当中都不是唯一的。一个index可能对应多个value。 不足之…...

制作麒麟V10-server-sp2镜像

1.挂载iso 文件到目录 mount -o loop /xxx.iso /mnt 这样mnt 目录下会有iso 解压相关的文件 2.修改源文件内容 vim /etc/yum.repos.d/ kylin_x86_64.repo 将里面的所有的源enabled 都改成 0 并添加一个新的源 [ks10-local] name Kylin Linux Advanced Server 10 - Local base…...

2.docker镜像的导入导出

目录 概述docker 常用命令下载导出导入镜像结束 概述 docker 常用命令 本章节使用到的命令&#xff0c;总结在此&#xff0c;后面有使用案例。 命令作用docker images显示镜像docker rmi $(docker images -q)删除系统上所有的镜像docker rmi -f强制删除多个镜像 &#xff1a…...

bs4介绍和遍历文档树、搜索文档树、案例:爬美女图片、 bs4其它用法、css选择器

bs4介绍和遍历文档树 BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库&#xff0c;解析库 需要安装模块&#xff1a;pip install beautifulsoup4 使用 解析库可以使用 lxml&#xff0c;速度快&#xff08;必须安装&#xff09; 可以使用python内置的 # html…...

微服务-开篇-个人对微服务的理解

从吃饭说起 个人理解新事物的时候喜欢将天上飞的理念转换成平常生活中的实践&#xff0c;对比理解这些高大上的名词&#xff0c;才能让我们减少恐慌的同时加深理解。废话不多说&#xff0c;我们从吃饭开始说起&#xff0c;逐渐类比出微服务的思想。 &#xff08;个人见解&…...

机器学习算法-集成学习

概念 集成学习是一种机器学习方法&#xff0c;它通过构建并结合多个机器学习器&#xff08;基学习器&#xff09;来完成学习任务。集成学习的潜在思想是即便某一个弱分类器得到了错误的预测&#xff0c;其他的弱分类器也可以将错误纠正回来。集成学习通常被视为一种元算法&…...

LINUX入门篇【4】开发篇--开发工具vim的使用

前言&#xff1a; 从这一篇开始&#xff0c;我们将正式进入使用LINUX进行写程序和开发的阶段&#xff0c;可以说&#xff0c;由此开始&#xff0c;我们才开始真正去使用LINUX。 介绍工具&#xff1a; 1.LINUX软件包管理器yum&#xff1a; 1.yum的介绍&#xff1a; 在LINUX…...

代码随想录算法训练营Day 50 || 309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

309.最佳买卖股票时机含冷冻期 力扣题目链接 给定一个整数数组&#xff0c;其中第 i 个元素代表了第 i 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 你不能同时…...

【C语言】【数据结构】【环形链表判断是否带环并返回进环节点】有数学推导加图解

1.判断是否带环&#xff1a; 用快慢指针 slow指针一次走一步&#xff0c;fast指针一次走两步 当两个指针相遇时&#xff0c;链表带环&#xff1b;两个指针不能相遇时&#xff0c;当fast走到倒数第一个节点或为空时&#xff0c;跳出循环返回空指针。 那么slow指针一次走一步&a…...

漏洞扫描-nuclei-poc编写

0x00 nuclei Nuclei是一款基于YAML语法模板的开发的定制化快速漏洞扫描器。它使用Go语言开发&#xff0c;具有很强的可配置性、可扩展性和易用性。 提供TCP、DNS、HTTP、FILE 等各类协议的扫描&#xff0c;通过强大且灵活的模板&#xff0c;可以使用Nuclei模拟各种安全检查。 …...

SpringBoot 自动配置

Condition 自定义条件&#xff1a; 定义条件类&#xff1a;自定义类实现Condition接口&#xff0c;重写 matches 方法&#xff0c;在 matches 方法中进行逻辑判断&#xff0c;返回boolean值 。 matches 方法两个参数&#xff1a; context&#xff1a;上下文对象&#xff0c;可…...

IP-guard WebServer 远程命令执行漏洞

IP-guard WebServer 远程命令执行漏洞 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: app"ip-guard" 漏洞复现1. 构造poc2. 访问文件3. 执行命令 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好地提高网络安全意识和技术水平。 任何人不…...

每次重启完IDEA,application.properties文件里的中文变成?

出现这种情况&#xff0c;在IDEA打开Settings-->Editor-->File Encodings 然后&#xff0c;你需要将问号改为你需要的汉字。 重启IDEA&#xff0c;再次查看你的.properties文件就会发现再没有变成问号了...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...