上饶警务-警车数据读取服务(udp)
zhongrj
2023-08-18 982bf012d98f9a77462ad69cdf3a0d0c8d628684
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package org.springblade.modules.netty.server;
 
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.modules.netty.config.MyDecoder;
import org.springblade.modules.netty.handle.UdpServerHandler;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
 
/**
 * updServer udp服务端
 *
 * @author zhongrj
 * @date 2023-02-21
 */
@Component
public class UdpServer {
 
    private static Logger LOG = LoggerFactory.getLogger(UdpServer.class);
 
 
    //给管道抽象出接口,给Channel更多的能力和配置,例如Channel的状态,参数,IO操作
    //使用ChannelPipeline实现自定义IO
    //Channel channel;
    @Async("taskExecutor")
    public void run(int port) {
        //启动服务
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        //优化使用的线程
        final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
 
        try {
            //udp不能使用ServerBootstrap
            Bootstrap b = new Bootstrap();
            //设置UDP通道
            b.group(workerGroup).channel(NioDatagramChannel.class)
                    //设置udp的管道工厂
                    .handler(new ChannelInitializer<NioDatagramChannel>() {
                        //NioDatagramChannel标志着是UDP格式的
                        @Override
                        protected void initChannel(NioDatagramChannel ch)
                                throws Exception {
                            // TODO Auto-generated method stub
                            //创建一个执行Handler的容器
                            ChannelPipeline pipeline = ch.pipeline();
//                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast("decoder",new MyDecoder());
//                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 4, 4, -8, 0));
                            //执行具体的自定义处理器
                            pipeline.addLast(group, "handler", new UdpServerHandler());
                        }
 
                    })//初始化处理器
 
                    //true / false 多播模式(UDP适用),可以向多个主机发送消息
                    .option(ChannelOption.SO_BROADCAST, true)
                    // 设置UDP读缓冲区为2M
                    .option(ChannelOption.SO_RCVBUF, 2048 * 1024)
                    // 设置UDP写缓冲区为1M
                    .option(ChannelOption.SO_SNDBUF, 1024 * 1024);
 
            // 绑定端口,开始接收进来的连接
            ChannelFuture f = b.bind(port).sync();
            //获取channel通道
            System.out.println("UDP Server 启动,端口:" + port);
            // 等待服务器 socket 关闭 。
            // 这不会发生,可以优雅地关闭服务器。
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅退出 释放线程池资源
            group.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
 
}