Springboot搭建Netty+Socket+Udp服务端和客户端

一: 服务端

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: 项目启动,这里忽略,加的话参考服务端

........

三: 测试 完成

猜你喜欢

转载自blog.csdn.net/qq_39706515/article/details/130768458