1. 添加maven关联依赖包
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Kafka依赖包-->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.12</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- netty依赖 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<!-- <version>4.1.51.Final</version>-->
</dependency>
</dependencies>
2. 编写springboot启动类
package com.hnu;
import com.hnu.server.UdpServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.scheduling.annotation.Async;
/**
* @description:
* @author: YUANHX
* @create: 1:56 下午
**/
@SpringBootApplication
@EnableDiscoveryClient
public class UdpApplication implements CommandLineRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(UdpApplication.class);
@Autowired
private UdpServer udpServer;
public static void main(String[] args) {
SpringApplication app = new SpringApplication(UdpApplication.class);
LOGGER.info("udp server starting.........................");
app.run(args);
}
@Async
@Override
public void run(String... args) throws Exception {
/**
* 使用异步注解方式启动netty udp服务端服务
*/
udpServer.bind();
}
}
3. 编写服务端代码
package com.hnu.server;
import com.hnu.handler.UdpSimpleChannelInboundHandler;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @description: UDPserver
* @author: YUANHX
* @create: 1:58 下午
**/
@Component
public class UdpServer {
private static final Logger LOGGER = LoggerFactory.getLogger(UdpServer.class);
/** netty udp port**/
@Value("${netty.udp.port}")
private int port;
public void bind(){
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try{
// UDP方式使用BootStrap
Bootstrap serverBootStrap = new Bootstrap();
serverBootStrap.group(eventLoopGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST,true)
.handler(new UdpSimpleChannelInboundHandler());
LOGGER.info("udp server start!....................");
ChannelFuture future = serverBootStrap.bind(port).sync();
future.channel().closeFuture().sync();
}catch (Exception e){
LOGGER.error("udp server start error;{}", e);
}finally {
LOGGER.info("udp server close!..................");
eventLoopGroup.shutdownGracefully();
}
}
}
package com.hnu.server.handler;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @description: 服务端I/O数据读写处理类
* @author: YUANHX
* @create: 2:24 下午
**/
public class UdpSimpleChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private static final Logger LOGGER = LoggerFactory.getLogger(UdpSimpleChannelInboundHandler.class);
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
try{
/*
//做类型转换,将msg转换成Netty的ByteBuf对象。
//ByteBuf类似于JDK中的java.nio.ByteBuffer 对象,不过它提供了更加强大和灵活的功能。
ByteBuf buf = packet.copy().content();
//通过ByteBuf的readableBytes方法可以获取缓冲区可读的字节数,
//根据可读的字节数创建byte数组
byte[] req = new byte[buf.readableBytes()];
//通过ByteBuf的readBytes方法将缓冲区中的字节数组复制到新建的byte数组中
buf.readBytes(req);
//通过new String构造函数获取请求消息。
String body = HexStringUtils.bytesToHexString(req).toUpperCase();
System.out.println(body);//打印收到的信息
//向客户端发送消息
String json = "hello world!!";
// 由于数据报的数据是以字符数组传的形式存储的,所以传转数据
byte[] bytes = json.getBytes("UTF-8");
DatagramPacket data = new DatagramPacket(Unpooled.copiedBuffer(bytes), packet.sender());
channelHandlerContext.writeAndFlush(data);//向客户端发送消息
*/
String str = packet.content().toString(CharsetUtil.UTF_8);
// 打印收到的消息
LOGGER.info("udp server recieve message:{}", str);
//收到udp消息后,可通过此方式原路返回的方式返回消息,例如返回时间戳
channelHandlerContext.writeAndFlush(
new DatagramPacket(
Unpooled.copiedBuffer(System.currentTimeMillis()/1000 +"", CharsetUtil.UTF_8),
packet.sender()
)
);
}catch (Exception e){
LOGGER.error("udp server recieve message error:{}", e);
}finally {
// channelHandlerContext.close();
}
}
}
4. 编写客户端代码
package com.hnu.client;
import com.hnu.client.handler.UdpClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
/**
* @description: udp client
* @author: YUANHX
* @create: 2:48 下午
**/
public class UdpClient {
public static void main(String[] args) throws Exception{
int port = 8301;
if(args != null && args.length > 0){
port = Integer.valueOf(args[0]);
}
new UdpClient().run(port);
}
public void run(int port) throws Exception{
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.group(eventLoopGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UdpClientHandler());
Channel channel = bootstrap.bind(0).sync().channel();
//向网段内所有机器广播
channel.writeAndFlush(
new DatagramPacket(
Unpooled.copiedBuffer("发个测试信息", CharsetUtil.UTF_8),
// new InetSocketAddress("255.255.255.255", port)
new InetSocketAddress("192.168.3.9", port)
)
).sync();
//客户端等待15s用于接收服务端的应答消息,然后退出并释放资源
if(!channel.closeFuture().await(15000L)){
System.out.println("查询超时!");
}
}catch (Exception e){
e.printStackTrace();
}finally {
eventLoopGroup.shutdownGracefully();
}
}
}
package com.hnu.client.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
/**
* @description:
* @author: YUANHX
* @create: 3:04 下午
**/
public class UdpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
String resp = packet.content().toString(CharsetUtil.UTF_8);
System.out.println("客户端接收结果:"+resp);
channelHandlerContext.close();
}
}