使用Java Socket实现GPS定位数据处理

在许多应用场景中,如车辆追踪、移动设备定位等,GPS定位数据的实时获取和处理至关重要。本文将介绍如何使用Java Socket编程来接收GPS设备发送的数据并进行处理。

业务说明
车辆追踪系统需要实时获取车辆的GPS定位信息。车辆上的GPS设备通过TCP连接发送其位置数据到服务器。
技术点:
Java Socket编程:使用Java的Socket API进行网络通信。
GPS定位数据:理解GPS数据格式,如NMEA 0183标准。
多线程处理:为每个连接创建线程以异步接收数据。

项目结构:

gps-tracking-system/
|-- src/
|   |-- main/
|   |   |-- java/
|   |   |   `-- com/
|   |   |       `-- example/
|   |   |           |-- GpsServer.java
|   |   |           |-- GpsDataHandler.java
|   |   |           |-- GpsDataParser.java
|   |   |           |-- BusinessDataService.java
|   |   |           `-- RabbitMqProducer.java
|   |   `-- resources/
|   |       `-- application.properties
|   `-- test/
|       `-- java/
|           `-- com/
|               `-- example/
|                   `-- GpsServerTest.java
`-- pom.xml

GpsServer.java:服务器启动类。
GpsDataHandler.java:Netty通道处理器,用于处理接收到的GPS数据。
GpsDataParser.java:解析GPS数据的类。
BusinessDataService.java:业务数据处理服务,负责将解析后的数据发送到MQ。
RabbitMqProducer.java:RabbitMQ生产者实现。
application.properties:应用配置文件。
GpsServerTest.java:服务器的单元测试类。
Maven依赖:
在pom.xml文件中,您需要添加以下依赖:

<dependencies>
    <!-- Netty -->
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.68.Final</version>
    </dependency>
    
    <!-- SLF4J API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.30</version>
    </dependency>
    
    <!-- Logback Classic -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    
    <!-- RabbitMQ Java Client -->
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>5.10.0</version>
    </dependency>
    
    <!-- JUnit for testing -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

在这里插入图片描述
服务器启动类(GpsServer.java):

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.io.IOException;
import java.util.Properties;

public class GpsServer {

    private final int port;

    public GpsServer() throws IOException {
        Properties props = new Properties();
        props.load(getClass().getClassLoader().getResourceAsStream("application.properties"));
        this.port = Integer.parseInt(props.getProperty("gps.server.port"));
    }

    public void run() throws InterruptedException {
    
        MqProducer mqProducer = new RabbitMqProducer("mq-broker1:5672"); 
        BusinessDataService businessDataService = new BusinessDataService(mqProducer);
    
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) {
                     ch.pipeline().addLast(new GpsDataHandler(businessDataService));
                 }
             });

            b.bind(port).sync().channel().closeFuture().await();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new GpsServer().run();
    }
}

GPS数据处理通道(GpsDataHandler.java):

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GpsDataHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = LoggerFactory.getLogger(GpsDataHandler.class);
    private final BusinessDataService businessDataService;

    public GpsDataHandler(BusinessDataService businessDataService) {
        this.businessDataService = businessDataService;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        try {
            byte[] data = new byte[in.readableBytes()];
            in.readBytes(data);
            String gpsData = new String(data, StandardCharsets.UTF_8);
            businessDataService.processBusinessData(gpsData);
        } catch (Exception e) {
            logger.error("Error processing GPS data", e);
        } finally {
            in.release();
            ctx.close(); // Close the connection after processing
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("Exception caught in GPS data handler", cause);
        ctx.close();
    }
}

业务数据服务(BusinessDataService.java):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BusinessDataService {

    private static final Logger logger = LoggerFactory.getLogger(BusinessDataService.class);
    // MQ客户端或生产者,具体实现根据所使用的MQ进行调整
    private final MqProducer mqProducer;

    public BusinessDataService(MqProducer mqProducer) {
        this.mqProducer = mqProducer;
    }

    public void processBusinessData(String gpsData) {
        try {
            BusinessGpsData businessData = GpsDataParser.parse(gpsData);
            if (businessData != null) {
                mqProducer.send(businessData);
                logger.info("Business GPS data sent to message queue: {}", businessData);
            }
        } catch (Exception e) {
            logger.error("Error processing business GPS data", e);
        }
    }
}

业务GPS数据解析器(GpsDataParser.java):


    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    public class GpsDataParser {

        // 假设GPS数据格式为: $GPGGA,xxx,xxx,xxx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx*
        private static final Pattern GPGGA_PATTERN = Pattern.compile("\\$GPGGA,\\d{2},\\d{2},(\\d{2}\\.\\d{7}),(\\d{3}),(\\d{2}\\.\\d{7}),([NS]),(\\d{3}\\.\\d{7}),([EW]),\\d{2}\\.\\d,\\d{2}\\.\\d,\\d{2},M,\\d{2},M,\\d{2},\\d{2}\\*[0-9A-F]{2}");

        /**
         * 例如,提取车辆ID、经纬度、时间戳等信息,并创建BusinessGpsData对象
         * 解析NMEA 0183标准的GPGGA语句
         * @param nmeaSentence GPS数据字符串
         * @return 解析后的BusinessGpsData对象
         */
         
        public static BusinessGpsData parse(String nmeaSentence) {
            Matcher matcher = GPGGA_PATTERN.matcher(nmeaSentence);
            if (matcher.find()) {
                double latitude = Double.parseDouble(matcher.group(1));
                String latHemisphere = matcher.group(3);
                double longitude = Double.parseDouble(matcher.group(4));
                String longHemisphere = matcher.group(6);

                // 转换经纬度为统一格式
                latitude = latHemisphere.equals("S") ? -latitude : latitude;
                longitude = longHemisphere.equals("W") ? -longitude : longitude;

                return new BusinessGpsData(
                        latitude,
                        longitude,
                        // 此处添加其他解析字段...
                        matcher.group(2) // 时间戳
                );
            }
            return null;
        }
    }
   // 定义业务GPS数据的字段,如车辆ID、经纬度、时间戳等
    class BusinessGpsData {
        private final double latitude;
        private final double longitude;
        // 其他业务字段...

        public BusinessGpsData(double latitude, double longitude, String timestamp) {
            this.latitude = latitude;
            this.longitude = longitude;
            // 初始化其他业务字段...
            this.timestamp = timestamp;
        }

        // Getters and Setters
    }

消息队列生产者接口(MqProducer.java):

public interface MqProducer {
    void send(BusinessGpsData businessData);
}

消息队列生产者实现(RabbitMqProducer.java):

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class RabbitMqProducer implements MqProducer {

    private final String queueName;
    private final ConnectionFactory factory;
    private Connection connection;
    private Channel channel;

    public RabbitMqProducer(String host) {
        this.queueName = "gps_data_queue";
        this.factory = new ConnectionFactory();
        this.factory.setHost(host);
        try {
            this.connection = factory.newConnection();
            this.channel = connection.createChannel();
            this.channel.queueDeclare(queueName, true, false, false, null);
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
            // Handle exception
        }
    }

    @Override
    public void send(BusinessGpsData businessData) {
        String message = "BusinessGpsData [" +
                "latitude=" + businessData.getLatitude() +
                ", longitude=" + businessData.getLongitude() +
                // 其他字段...
                ", timestamp=" + businessData.getTimestamp() +
                "]";
        try {
            channel.basicPublish("", queueName, null, message.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
            // Handle exception
        }
    }

    // Ensure resources are cleaned up
    public void close() {
        if (channel != null) {
            try {
                channel.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

配置文件(resources/application.properties):

gps.server.port=6789
mq.broker.list=mq-broker1:5672

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954202.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Unity踩坑】Unity中提示缺少Visual Studio组件

问题&#xff1a; 在Unity中选择UWP平台时&#xff0c;提示Visual Studio缺少组件。 Selected Visual Studio is missing required components and may not be able to build the generated project. 解决方案&#xff1a; 在Visual Studio Installer里&#xff0c;安装上&quo…

ADC(Analog-to-digital converter)模拟-数字转换器

ADC简介 ADC&#xff08;Analog-to-Digital Converter&#xff09;&#xff0c;即模拟-数字转换器&#xff0c;是一种将模拟信号转换成数字信号的电子设备。它在现代电子系统中扮演着至关重要的角色&#xff0c;广泛应用于传感器信号处理、通信系统、医疗设备、工业自动化等多…

ASP.NET Core - 日志记录系统(二)

ASP.NET Core - 日志记录系统&#xff08;二&#xff09; 2.4 日志提供程序2.4.1 内置日志提供程序2.4.2 源码解析 本篇接着上一篇 ASP.NET Core - 日志记录系统(一) 往下讲&#xff0c;所以目录不是从 1 开始的。 2.4 日志提供程序 2.4.1 内置日志提供程序 ASP.NET Core 包括…

从零开始深度学习:(1)张量的常用操作

孩子们&#xff0c;懒大王回来了&#xff01; 正如标题所说&#xff0c;今天我们继续开始新的篇章&#xff0c;我们要开始高强度学习深度学习的相关内容&#xff0c;这个专栏内容较多、全是干货&#xff0c;我们还会在合适的地方进行拓展一些额外的语法或者别的相关知识&#…

【Idea】编译Spring源码 read timeout 问题

Idea现在是大家工作中用的比较多的开发工具&#xff0c;尤其是做java开发的&#xff0c;那么做java开发&#xff0c;了解spring框架源码是提高自己技能水平的一个方式&#xff0c;所以会从spring 官网下载源码&#xff0c;导入到 Idea 工具并编译&#xff0c;但是发现build的时…

C++|CRC校验总结

参考&#xff1a; Vector - CAPL - CRC算法介绍 开发工具 > CRC校验工具 文章目录 简介CRC-8CRC-16CRC-32 简介 循环冗余校验&#xff08;Cyclic Redundancy Check&#xff0c;简称CRC&#xff09;是一种数据校验算法&#xff0c;广泛用于检测数据传输或存储过程中的错误。…

【Linux】11.Linux基础开发工具使用(4)

文章目录 3. Linux调试器-gdb使用3.1 背景3.2 下载安装3.3 使用gdb查询3.4 开始使用 3. Linux调试器-gdb使用 3.1 背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须…

windows系统“acadres.dll”文件丢失或错误导致游戏运行异常如何解决?windows系统DLL文件修复方法

acadres.dll是存放在windows系统中的一个重要dll文件&#xff0c;缺少它可能会造成部分游戏不能正常运行。当你的电脑弹出提示“无法找到acadres.dll”或“计算机缺少acadres.dll”等错误问题&#xff0c;请不用担心&#xff0c;我们将深入解析DLL文件错误的成因&#xff0c;并…

小程序如何引入腾讯位置服务

小程序如何引入腾讯位置服务 1.添加服务 登录 微信公众平台 注意&#xff1a;小程序要企业版的 第三方服务 -> 服务 -> 开发者资源 -> 开通腾讯位置服务 在设置 -> 第三方设置 中可以看到开通的服务&#xff0c;如果没有就在插件管理中添加插件 2.腾讯位置服务…

【AIGC-ChatGPT进阶提示词指令】心灵修复师:一个基于情感共鸣的智慧对话系统设计

引言 在当今快节奏的生活中&#xff0c;心理健康问题日益凸显。如何借助人工智能技术&#xff0c;构建一个既富有温度又专业可靠的心理支持系统&#xff0c;成为了一个值得深入探讨的课题。本文将详细介绍一个名为"心灵修复师"的对话系统设计&#xff0c;这个系统通…

计算机网络 (44)电子邮件

一、概述 电子邮件&#xff08;Electronic Mail&#xff0c;简称E-mail&#xff09;是因特网上最早流行的应用之一&#xff0c;并且至今仍然是因特网上最重要、最实用的应用之一。它利用计算机技术和互联网&#xff0c;实现了信息的快速、便捷传递。与传统的邮政系统相比&#…

《leetcode-runner》【图解】如何手搓一个debug调试器——调试程序【JDI开发】【万字详解】

前文&#xff1a; 《leetcode-runner》如何手搓一个debug调试器——引言 《leetcode-runner》如何手搓一个debug调试器——架构 《leetcode-runner》如何手搓一个debug调试器——指令系统 本文主要聚焦于如何编写调试程序 背景 在leetcode算法背景下&#xff0c;用户只编写了…

小米vela系统(基于开源nuttx内核)——openvela开源项目

前言 在 2024 年 12 月 27 日的小米「人车家全生态」合作伙伴大会上&#xff0c;小米宣布全面开源 Vela 操作系统。同时&#xff0c;OpenVela 项目正式上线 GitHub 和 Gitee&#xff0c;采用的是比较宽松的 Apache 2.0 协议&#xff0c;这意味着全球的开发者都可以参与到 Vela…

【 PID 算法 】PID 算法基础

一、简介 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&#xff09;、Differential&#xff08;微分&#xff09;的缩写。也就是说&#xff0c;PID算法是结合这三种环节在一起的。粘一下百度百科中的东西吧。 顾名思义&#xff0c;…

使用 WPF 和 C# 绘制覆盖网格的 3D 表面

此示例展示了如何使用 C# 代码和 XAML 绘制覆盖有网格的 3D 表面。示例使用 WPF 和 C# 将纹理应用于三角形展示了如何将纹理应用于三角形。此示例只是使用该技术将包含大网格的位图应用于表面。 在类级别&#xff0c;程序使用以下代码来定义将点的 X 和 Z 坐标映射到 0.0 - 1.…

为深度学习创建PyTorch张量 - 最佳选项

为深度学习创建PyTorch张量 - 最佳选项 正如我们所看到的&#xff0c;PyTorch张量是torch.Tensor​ PyTorch类的实例。张量的抽象概念与PyTorch张量之间的区别在于&#xff0c;PyTorch张量为我们提供了一个可以在代码中操作的具体实现。 在上一篇文章中&#xff0c;我们看到了…

Linux下源码编译安装Nginx1.24及服务脚本实战

1、下载Nginx [rootlocalhost ~]# wget -c https://nginx.org/download/nginx-1.24.0.tar.gz2、解压 [rootlocalhost ~]# tar xf nginx-1.24.0.tar.gz -C /usr/local/src/3、安装依赖 [rootlocalhost ~]# yum install gcc gcc-c make pcre-devel openssl-devel -y4、 准备 N…

4、dockerfile实现lnmp和elk

dockerfile实现lnmp 使用dockerfile n&#xff1a;nginx&#xff0c;172.111.0.10 m&#xff1a;mysql&#xff0c;172.111.0.20 p&#xff1a;php&#xff0c;172.111.0.30 安装配置nginx 1、准备好nginx和wordpress安装包 2、配置dockerfile 3、配置nginx主配置文件ngin…

一文通透OpenVLA及其源码剖析——基于Prismatic VLM(SigLIP、DinoV2、Llama 2)及离散化动作预测

前言 当对机器人动作策略的预测越来越成熟稳定之后(比如ACT、比如扩散策略diffusion policy)&#xff0c;为了让机器人可以拥有更好的泛化能力&#xff0c;比较典型的途径之一便是基于预训练过的大语言模型中的广泛知识&#xff0c;然后加一个policy head(当然&#xff0c;一开…

《操作系统真象还原》第十三章——磁盘驱动程序

文件系统磁盘创建 创建磁盘 进入bochs安装目录&#xff0c;输入以下命令 ./bin/bximage 然后按照以下步骤创建硬盘 修改硬盘配置 vim boot.disk 添加以下代码行 ata0-slave: typedisk, path"hd80M.img", modeflat,cylinders162,heads16,spt63 完整配置如下 …