# NettyUdpDemo
**Repository Path**: arthurliuyuhao/netty-udp-demo
## Basic Information
- **Project Name**: NettyUdpDemo
- **Description**: Netty实战网络编程源码
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2023-11-06
- **Last Updated**: 2023-11-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
### 一、Netty简单介绍
Netty是一个基于NIO的客户、服务端开发框架,使用Netty能够使你快速和简单的开发出一个网络应用,例如实现某种协议的客户、服务端应用。Netty相当于简化和流程化了网络应用的编程过程,例如基于UDP和TCP的socket开发。
“快速而简单”并不意味着生成的应用程序将面临可维护性或性能问题。Netty是经过精心设计的,其经验来自FTP、SMTP、HTTP以及各种二进制和基于文本的传统协议的实现。因此,Netty成功地找到了一种不妥协地实现易于开发、性能、稳定性和灵活性的方法。
其实使用更加简洁的描述的话就是,Netty是对NIO的一次封装,因为JAVA直接使用NIO的话体验感并不是特别好。使用Netty可以实现快速搭建网络通信服务端。
**Features(特点)**
1. Design(设计性)
2. Ease of use(易用性)
3. Performance(高性能)
4. Security(安全)
5. Community(社区性)
> 关于Netty的详细介绍会在其他文章与大家见面。
### 二、关于UDP的内容
UDP(User Datagram Protocol),用户数据报协议。是OSI(Open System Interconnection,开放式系统互联)中的一种协议,提供面向事务简单不可靠传输服务。它具有下面几个特点:
**1.客户端与服务端之间是不需要连接的,即无连接性。
2.传输不可靠,不会因为服务端未正常收到数据或解析数据导致让客户端重新发送。
3.传输过程延迟小。
4.传输效率高。**
当然在这里就只是列举了几个相对优秀的特点,这几个特点引发了一部分比较适合的场景:
DNS、TFTP、SNMP、屏幕信息显示、设备数据上传等。
### 三、JAVA基于Netty搭建UDP服务端
项目框架:基于SpringBoot搭建,更适用于实际生产业务使用。
#### 引入maven库:
```
io.netty
netty-all
5.0.0.Alpha2
```
#### 构建消息处理器:
```
package com.example.udpDemo.socket.udp;
import cn.hutool.core.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
/**
* @author wangdachuan
* @version 1.0
* @date 2023/3/14 23:12
**/@Slf4j
@Component
public class UdpServerHandler extends SimpleChannelInboundHandler {
@Override
protected void messageReceived(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket)
throws Exception {
InetSocketAddress sender = datagramPacket.sender();
String ip = sender.getAddress().getHostAddress();
ByteBuf buf = datagramPacket.copy().content();
try {
byte[] data = new byte[buf.readableBytes()];
buf.readBytes(data);
String dataStr = HexUtil.encodeHexStr(data);
log.info("收到IP:{},发送的数据:{}", ip, dataStr);
// 下面进行业务代码处理
}catch (Exception e){
e.printStackTrace();
}
// TCP返回数据写法
//channelHandlerContext.channel().writeAndFlush("1");
// UDP返回数据写法
channelHandlerContext.channel().writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(HexUtil.decodeHex("1")), datagramPacket.sender()));
}
}
```
SimpleChannelInboundHandler 这个是Netty实现UDP协议需要继承的类。
通过重写messageReceived这个方法来对接收到的消息做业务处理。
UDP返回方法需要注意,跟TCP直接返回也有区别,需要通过DatagramPacket进行封装后返回给客户端。
```
channelHandlerContext.channel().writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(HexUtil.decodeHex("1")), datagramPacket.sender()));
```
#### 构建Netty启动器
```
package com.example.udpDemo.socket.udp;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author wangdachuan
* @version 1.0
* @date 2023/3/14 23:25
**/@Slf4j
@Component
public class UdpServer {
public void run(){
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UdpServerHandler());
ChannelFuture channelFuture = b.bind(8081).sync();
log.info("netty构建的UDP服务启动: [port:{}]", 8081);
// 等待服务器socket关闭
channelFuture.channel().closeFuture().await();
} catch (Exception e) {
log.error("netty构建的UDP服务启动异常-" + e.getMessage());
} finally {
group.shutdownGracefully();
}
}
}
```
[NioEventLoopGroup] 是用来处理I/O操作的多线程事件循环器,Netty提供了许多不同的[EventLoopGroup]的实现用来处理不同传输协议。
**下面就是实现UDP的重点了:**
NioDatagramChannel:是一个能收发UDP包的通道,它实现了Netty用来接收UDP包的通道的接口:DatagramChannel 。
其他的参数都是Netty常见参数。
#### 通过项目启动后加载UDP服务
```
package com.example.udpDemo.socket;
import cn.hutool.core.thread.ThreadUtil;
import com.example.udpDemo.socket.udp.UdpServer;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* @author wangdachuan
* @version 1.0
* @date 2023/3/14 23:31
**/@Slf4j
@Component
public class StartRunner implements ApplicationRunner {
@Resource
private UdpServer udpServer;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("开始启动Netty服务");
// 启动UDP服务
ThreadUtil.execAsync(()->{
udpServer.run();
});
}
}
```
到这里,通过Netty构建UDP服务端已经开发完成了。
### 四、验证
**项目启动:**
![[udp start.png]]
收发消息:
![[udp message.png]]
### 五、源码获取
代码地址:https://gitee.com/wyc_01/netty-udp-demo.git
### 六、总结
这是在开发工作中用到的UDP编程代码整理而来,如果大家看的过程中有觉得不对的,或者更好的方法,希望大家能够指出来。
`希望大家多多关注+点赞+收藏 🙏🙏,你们的鼓励是我不断前进的动力💪💪!!!`