本次使用的是netty做为接收协议,考虑到其他各种工业以太网对于java实现接收全是采取了Netty,干脆自己实现Netty进行解析。由于我使用的netty版本是5.0.0.Alpha2,可能会一些和4.1.2有不同的地方,还请注意
不多说了直接上代码看看如何。
老规矩,在springboot项目的创建中,本人通常都是采用了启动项做为netty在项目中的启动案列,如果有其他需求可以采用controller层做接口方式进行一次手动启动。
@Slf4j
@Component
public class StartComponent implements CommandLineRunner {
@Value("${Netty.port}")
private Integer port;
@Resource
private NettyUdpBootstrapServerImpl nettyUdpBootstrapServer;
@Override
public void run(String... args) throws Exception {
new Thread(this::creatNetty).start();
}
public void creatNetty(){
try {
log.info("netty start .....");
nettyUdpBootstrapServer.startup(port);
}catch (Exception e){
log.error(e.getMessage());
}
}
}
接下启动的方式肯定要对这个接口进行实现,
接口具体包含的方法只有两个
@Component
public interface NettyUdpBootstrapServer {
//启动方法
void startup(int port);
//结束方法
void shutdown();
}
对于这个接口我先实现了一个抽象方法作为对netty适配的搭建
@Component
public abstract class BootNettyUdpAbstractBootstrapServer implements NettyUdpBootstrapServer {
@Autowired
private MoveTask moveTask;
public void initChannelHandler(ChannelPipeline channelPipeline){
channelPipeline.addLast(new UdpHandler(moveTask));
}
}
当然这边如果你想把自己的service的实现类能够装配进去只能在这个层进行使用,因为接下来的UdpHandler是手动new进去的,不是spring自己装配的,否则就会找不到这个bean对象。
接下来就是主要的方法实现就是按照正常的netty实现方式,不过由于是udp所以是采用NioDatagramChannel
@Slf4j
@Service
public class NettyUdpBootstrapServerImpl extends BootNettyUdpAbstractBootstrapServer {
private EventLoopGroup eventLoopGroup;
@Override
public void startup(int port) {
eventLoopGroup=new NioEventLoopGroup(5);
try {
Bootstrap serverBootstrap =new Bootstrap();
serverBootstrap =serverBootstrap.group(eventLoopGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST,true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
@Override
protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception {
initChannelHandler(nioDatagramChannel.pipeline());
}
});
ChannelFuture f =serverBootstrap.bind(port).sync();
if (f.isSuccess()){
log.info("netty udp start"+port);
f.channel().closeFuture().sync();
}
}catch (Exception e){
log.error(e.getMessage());
}
finally {
log.info("netty udp close");
eventLoopGroup.shutdownGracefully();
}
}
@Override
public void shutdown() {
eventLoopGroup.shutdownGracefully();
}
}
接下来就是到了关键地方了,就是本次的逻辑处理方法了
@Slf4j
@Component
public class UdpHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private MoveTask moveTask;
@Autowired
public UdpHandler(@Qualifier("moveTaskImpl")MoveTask moveTask) {
this.moveTask = moveTask;
}
/**
* 此处是接收UDP消息的内容将数据传入流程开始的部分
* @param channelHandlerContext
* @param datagramPacket
* @throws Exception
*/
@Override
public void messageReceived(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
//接收数据则是采用了对于datagramPacket.content的处理
ByteBuf b =datagramPacket.content();
//此处就是看自己的处理方式了
//下面的就是udp的返回方式buffer就是bytebuf类
DatagramPacket resData =new DatagramPacket(buffer,datagramPacket.sender());
channelHandlerContext.writerAndflush(resDate);
}
}
其中有一部分本次省去了就是关于当中的处理逻辑,因为不同的业务所以处理流程不同,所以本人不在此处上传自己的处理业务,具体来说这个可以对于任意的udp接收方当做好的模板。具体的报文大家可以先搭建了后再打印下自己看一下了