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

2 篇文章 0 订阅
2 篇文章 0 订阅

一: 服务端

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

........

三: 测试 完成

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是使用SpringBoot整合Netty实现UDP服务的代码示例: 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-transport-native-epoll</artifactId> <version>4.1.63.Final</version> <classifier>linux-x86_64</classifier> <scope>provided</scope> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.63.Final</version> </dependency> ``` 接下来,创建一个UDP服务器类,如下所示: ```java import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class UdpServer { @Value("${udp.port}") private int port; public void start() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioDatagramChannel.class) .option(ChannelOption.SO_BROADCAST, true) .handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new UdpServerHandler()); } }); ChannelFuture future = bootstrap.bind(port).sync(); future.channel().closeFuture().await(); } finally { group.shutdownGracefully(); } } } ``` 然后,创建一个UDP服务器处理程序类,如下所示: ```java import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; public class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> { @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { // 处理接收到的UDP数据包 String message = packet.content().toString(CharsetUtil.UTF_8); // 在这里进行业务处理 System.out.println("接收到UDP消息:" + message); } } ``` 最后,在Spring Boot的启动类中添加以下代码: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application implements CommandLineRunner { @Autowired private UdpServer udpServer; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { udpServer.start(); } } ``` 现在,你可以在配置文件中指定UDP服务器的口号(如application.properties或application.yml),然后运行Spring Boot应用程序来启动UDP服务器。 这样就实现了使用SpringBoot整合Netty实现UDP服务的代码。你可以根据自己的需求进行进一步的业务处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wcybaonier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值