一: 服务端
1: 服务端主启动类
package com.idc.config.udpsocket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* udp服务端
*
* @author wcybaonier
*/
@Component
public class UdpServer {
@Resource
private UdpServerHandler handler;
public void start(int port) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
// 主线程处理
.channel(NioDatagramChannel.class)
// 广播
.option(ChannelOption.SO_BROADCAST, true)
// 设置读缓冲区为2M
.option(ChannelOption.SO_RCVBUF, 2048 * 1024)
// 设置写缓冲区为1M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024)
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
protected void initChannel(NioDatagramChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new NioEventLoopGroup(), handler);
}
});
ChannelFuture f = bootstrap.bind(port).sync();
System.out.println("ODF----Udp---Socket------服务器正在监听......: "+port);
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
2:业务处理类(接收消息等)
package com.idc.config.udpsocket;
import com.idc.common.exception.CommonRuntimeException;
import com.idc.entity.odf.dto.LightingStatus;
import com.idc.mapper.OdfMapper;
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.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
/**
* 服务端业务处理
*
* @author wcybaonier
*/
@Slf4j
@Component
public class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Resource
private OdfMapper odfMapper;
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
String msg = packet.content().toString(StandardCharsets.UTF_8);
log.info("ODF-Socket------服务端接收到消息:" + packet.content().toString(StandardCharsets.UTF_8));
if (StringUtils.isBlank(msg)){
throw new CommonRuntimeException("ODF---Udp---Socket------加载客户端报文为空,请联系厂商!");
}
log.info("ODF-Socket------加载客户端报文......【" + ctx.channel().id() + "】" + " :" + msg);
/**
* 下面可以解析数据,保存数据,生成返回报文,将需要返回报文写入write函数
* 在这里可以设置异步执行 提交任务到该channel的taskQueue 中
*/
ctx.channel().eventLoop().execute(() -> {
// 如果不包含逗号, 那么格式不对 约定格式为 : 序列号,deviceid,shelfNo,moduleNo,termNo,state
if (!msg.contains(",")){
throw new CommonRuntimeException("ODF---Udp---Socket-------加载客户端报文格式不正确,请联系厂商!");
}
try {
String[] split = msg.split(",");
if (split.length != 6){
throw new CommonRuntimeException("ODF---Udp---Socket-------加载客户端报文长度不正确,请联系厂商!");
}
//开始修改 admin
LightingStatus lightingStatus = new LightingStatus();
lightingStatus.setSerialNumber(split[0]);
lightingStatus.setDeviceId(split[1]);
lightingStatus.setShelfNo(split[2]);
lightingStatus.setModuleNo(split[3]);
lightingStatus.setTermNo(split[4]);
lightingStatus.setState(split[5]);
int i = odfMapper.updateTermStatus(lightingStatus);
log.info("ODF---Udp---Socket------亮灯状态更新条数......【" + i + "】" );
} catch (Exception e) {
e.printStackTrace();
}
});
// 向客户端发送消息 已经和厂商老头沟通,原报文返回
ByteBuf byteBuf = Unpooled.copiedBuffer(msg.getBytes(StandardCharsets.UTF_8));
ctx.writeAndFlush(new DatagramPacket(byteBuf, packet.sender()));
}
}
3: 项目启动类(项目启动自动监听端口)
package com.idc;
import com.idc.config.udpsocket.UdpServer;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.Resource;
/**
* @author wcybaonier
*/
@MapperScan("com.idc.mapper")
@SpringBootApplication
@Slf4j
@EnableScheduling
public class IdcPduApplication implements CommandLineRunner {
@Value("${netty.host}")
private String host;
@Value("${netty.port}")
private Integer port;
@Resource
private UdpServer udpServer;
public static void main(String[] args) {
SpringApplication.run(IdcPduApplication.class, args);
log.info("IdcPduApplication 启动成功!");
}
/**
* netty服务启动
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
log.info("ODF---Udp---Socket----neety服务器启动地址: "+host+":"+ port);
udpServer.start(port);
}
}
服务端完成!启动项目即可!!!
二: 客户端
1: 客户端主启动类
这里由于是测试,我写的main方法, 也可以和服务端一样改为跟随项目启动!!!
package com.ws.udpClient;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
/**
* udp客户端
*
* @author wcybaonier
*/
public class UdpClient {
public static void main(String[] args) {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
protected void initChannel(NioDatagramChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new UdpClientHandler());
}
});
Channel channel = bootstrap.bind(7102).sync().channel();
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 7101);
ByteBuf byteBuf = Unpooled.copiedBuffer("0,odf62e383c900005692,0,0,0,2".getBytes(StandardCharsets.UTF_8));
channel.writeAndFlush(new DatagramPacket(byteBuf, address)).sync();
channel.closeFuture().await();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
二: 业务处理类
package com.ws.udpClient;
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 java.nio.charset.StandardCharsets;
/**
* 客户端业务处理
*
* @author wcybaonier
*/
public class UdpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
//接受服务端发送的内容
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
System.out.println("客户端接收到消息:" + packet.content().toString(StandardCharsets.UTF_8));
// 向客户端发送消息
ByteBuf byteBuf = Unpooled.copiedBuffer("0,odf62e383c900005692,0,0,0,2".getBytes(StandardCharsets.UTF_8));
ctx.writeAndFlush(new DatagramPacket(byteBuf, packet.sender()));
}
}
3: 项目启动,这里忽略,加的话参考服务端
........