在 Android 上,一个完整的 UDP 通信模块应该是怎样的?

Android广播--实现基于UDP协议通信 一、什么是UDP协议 我们最常听到的就是TCP与UDP的区别,首先要明白TCP/IP网络模型,TCP/IP是互联网相关的各类协议族的总称,之所以命名为tcp/IP,是因为TCP、IP协议是两个很重要的协议。 这些协议可划分为四层:数据链路层、网络层、传输层、应用层。 应用层:文件传输、电子邮件、文件服务、虚拟终端 超文本传输协议(HTTP):万维网的基本协议 远程登陆(Telnet):提供远程访问其它主机功能,允许用户登录internet主机,并在这台主机上执行命令 文件传输:TFTP(简单文件 阅读详情

在 Android 上,一个完整的 UDP 通信模块应该是怎样的?

本文例子的所有代码在这里:

github 连接在这里 UDPSocketDemo

写在前面:
在上周写了一篇关于 TCP 和 UDP 概念区别对比的文章:

TCP与UDP差异对比分析

在这篇文章中,在可靠性、数据发送、适用场景等多个方面分析了二者的区别。而本文的目的是想给大家介绍下在 Android 设备上,一个手机通过热点连接另一个手机。这种场景下,完整的 UDP 通信模块应该考虑哪些方面,又应该如何优化,如何避开一些坑呢?

UDP 在 Java 中的使用

我们都知道,开发一个 Android 应用程序,目前大多数还是使用的是 Java 语言。在 Java 语言中怎么去使用 UDP 协议呢?

上篇文章中我们没说 Socket,其实 Socket 可以理解为对 TCP、UDP 协议在程序使用层面的封装,提供出一些 api 来供程序员调用开发,这就是 Socket 最表层的含义。

在 Java 中,与 UDP 相关的类有 DatagramSocket、DatagramPacket 等,关于他们的使用,这里不着重介绍,可以看下面这篇文章:

Java UDP Socket

好了,假设大家对他们的使用都已大概了解,可以正式开始本文的内容了。

初始化一个 UDPSocket

首先创建一个叫 UDPSocket 的类。

    public UDPSocket(Context context) {

        this.mContext = context;

        int cpuNumbers = Runtime.getRuntime().availableProcessors();
        // 根据CPU数目初始化线程池
        mThreadPool = Executors.newFixedThreadPool(cpuNumbers * POOL_SIZE);
        // 记录创建对象时的时间
        lastReceiveTime = System.currentTimeMillis();
    }

在构造方法里,我们进行下一些初始化操作,简单来说就是创建一个线程池,记录一下当前时间毫秒值,至于他们有什么用,再往下看:

    public void startUDPSocket() {
        if (client != null) return;
        try {
            // 表明这个 Socket 在设置的端口上监听数据。
            client = new DatagramSocket(CLIENT_PORT);

            if (receivePacket == null) {
                // 创建接受数据的 packet
                receivePacket = new DatagramPacket(receiveByte, BUFFER_LENGTH);
            }

            startSocketThread();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

这里我们首先创建了一个 DatagramSocket 作为“客户端”,其实 UDP 本身没有客户端和服务端的概念,只有发送方和接收方的概念,我们把发送方暂时当成是一个客户端吧。

创建 DatagramSocket 对象时,传入了一个端口号,这个端口号可以在一个范围内自己定义,表示这个 DatagramSocket 在此端口上监听数据。

然后又创建了一个 DatagramPacket 对象,作为数据的接收包。

最后调用 startSocketThread 启动发送和接收数据的线程。

    /**
     * 开启发送数据的线程
     */
    private void startSocketThread() {
        clientThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "clientThread is running...");
                receiveMessage();
            }
        });
        isThreadRunning = true;
        clientThread.start();

        startHeartbeatTimer();
    }

首先 clientThread 线程的目的是调用 DatagramSocket receive 方法,因为 receive 方法是阻塞的,不能放在主线程,所以自然开启一个子线程了。receiveMessage 就是处理接受到的 UDP 数据报,我们先不看接受数据的这个方法,毕竟还没人发消息呢,自然就谈不上收了。

心跳包保持“长连接”

来到本文的第一个重点,我们都知道 UDP 本身没有连接的概念。在 Android 端应用 UDP 和 TCP 的场景是一个手机连接另一个手机的热点,二者处在同一局域网中。在二者并不知道对方的存在时,怎么才能发现彼此呢?

通过心跳包的方式,双方都每隔一段时间发一个 UDP 包,如果对方接收到了,那就能知道对方的 ip,建立起通信了。

    private static final long TIME_OUT = 120 * 1000;
    private static final long HEARTBEAT_MESSAGE_DURATION = 10 * 1000;
    /**
     * 启动心跳,timer 间隔十秒
     */
    private void startHeartbeatTimer() {
        timer = new HeartbeatTimer();
        timer.setOnScheduleListener(new HeartbeatTimer.OnScheduleListener() {
            @Override
            public void onSchedule() {
                Log.d(TAG, "timer is onSchedule...");
                long duration = System.currentTimeMillis() - lastReceiveTime;
                Log.d(TAG, "duration:" + duration);
                if (duration > TIME_OUT) {//若超过两分钟都没收到我的心跳包,则认为对方不在线。
                    Log.d(TAG, "超时,对方已经下线");
                    // 刷新时间,重新进入下一个心跳周期
                    lastReceiveTime = System.currentTimeMillis();
                } else if (duration > HEARTBEAT_MESSAGE_DURATION) {//若超过十秒他没收到我的心跳包,则重新发一个。
                    String string = "hello,this is a heartbeat message";
                    sendMessage(string);
                }
            }

        });
        timer.startTimer(0, 1000 * 10);
    }

这段心跳的目的就是每隔十秒通过 sendMessage 发送一个消息,看看对方能不能收到。若对方收到消息,则刷新下 lastReceiveTime 的时间。

这里我每隔十秒向对方发送了一个字符串。

    private static final String BROADCAST_IP = "192.168.43.255";
    /**
     * 发送心跳包
     *
     * @param message
     */
    public void sendMessage(final String message) {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    InetAddress targetAddress = InetAddress.getByName(BROADCAST_IP);

                    DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), targetAddress, CLIENT_PORT);

                    client.send(packet);

                    Log.d(TAG, "数据发送成功");

                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });
    }

这里就是发送一个消息的代码。最初在填写 DatagramPacket 的参数之时,我有一个疑问,那个 targetAddress 其实是自己的 ip 地址。问题来了,我填写了自己的 ip 地址和对方的端口,怎么可能找得到对方呢?你可能有一个疑惑 “192.168.43.255” 这个自己的 ip 地址是怎么来的,为什么要这么定义?

首先 android 手机开启热点,可以理解成一个网关,有一个默认的 ip 地址:”192.168.43.1”

这个 ip 地址不是我瞎编的一个,在 Android 源码之中,就是这么定义的:

WifiStateMachine

                        ifcg = mNwService.getInterfaceConfig(intf);
                        if (ifcg != null) {
                            /* IP/netmask: 192.168.43.1/255.255.255.0 */
                            ifcg.setLinkAddress(new LinkAddress(
                                    NetworkUtils.numericToInetAddress("192.168.43.1"), 24));
                            ifcg.setInterfaceUp();

                            mNwService.setInterfaceConfig(intf, ifcg);
                        }

所以我是知道所谓打开热点一方的 ip 地址,而 UDP 发送消息时还有一个特性,就是发出去的消息,处在整个网关的设备是都可以接收到的,所以我自己的 ip 地址就定为了 “192.168.43.255”,所以这个 ip 地址和 “192.168.43.1” 在同一网关中,你发送的消息,它是可以收到的。

至于怎么判断两个 ip 地址是否处在同一网段中:

判断两个IP大小及是否在同一个网段中

来做一个阶段总结:

首先我们创建了一个发送端 DatagramSocket,启动了一个心跳程序,每间隔一段时间发送一个心跳包。

因为我知道热点方的 ip 地址是默认的 “192.168.43.1”,并且 UDP 的特性就是发送的消息同一网段的设备都可以收到。所以发送方的 ip 地址定为了与热点一方处在同一网段的 “192.168.43.255”。

事件与数据

事件与数据这两个模块与业务就紧密相关了。

先来说数据,双方发送的数据格式你们可以随意定义,当然我觉得还是定义成常规的 Json 格式就好。其中可以包含一些关键的事件字段:比如广播心跳包、收到心跳包给对方上线的应答包、超时的下线包、以及各种业务相关的数据等等。

当然发送数据时是转换成二进制数组发送的。发送中文字符、图片等都没有问题,但是可能有一些细节需要注意,随时 google 一下就好了。

再来说下事件:

与业务无关的事件有哪些?

比如:
DatagramSocket.send 方法之后就是发送数据成功的事件;

DatagramSocket.receive 方法之后是数据接收成功的事件;

在心跳包发送一段时间,仍没有接到回信时,是连接超时的事件;

与业务相关的事件就和我们上文提到的数据类型有关了,设备上线,心跳包回应等等。

事件又如何发送出去,通知到各个页面呢?用 Listener、或者其他事件总线的三方库都没问题,看你自己选择了。

处理接收的消息

    /**
     * 处理接受到的消息
     */
    private void receiveMessage() {
        while (isThreadRunning) {
            try {
                if (client != null) {
                    client.receive(receivePacket);
                }
                lastReceiveTime = System.currentTimeMillis();
                Log.d(TAG, "receive packet success...");
            } catch (IOException e) {
                Log.e(TAG, "UDP数据包接收失败!线程停止");
                stopUDPSocket();
                e.printStackTrace();
                return;
            }

            if (receivePacket == null || receivePacket.getLength() == 0) {
                Log.e(TAG, "无法接收UDP数据或者接收到的UDP数据为空");
                continue;
            }

            String strReceive = new String(receivePacket.getData(), 0, receivePacket.getLength());
            Log.d(TAG, strReceive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());

            //解析接收到的 json 信息

            // 每次接收完UDP数据后,重置长度。否则可能会导致下次收到数据包被截断。
            if (receivePacket != null) {
                receivePacket.setLength(BUFFER_LENGTH);
            }
        }
    }

处理接收消息时,有几个值得注意的点:

  1. receive 方法是阻塞的,没收到数据包时会一直阻塞,所以要放到子线程中;
  2. 每次接收到消息之后,重新调用 receivePacket.setLength;
  3. 收到消息刷新lastReceiveTime的值,暂停心跳包的发送;

处理收到的数据具体在业务上就是刚才我们谈的发送数据的问题,视业务而定。

“用户”的概念

上文已经谈过了 UDP 的特性,假如一个手机已经开启了热点,若多个手机与他相连接,则多个手机发送的消息它都可以收到。如果发送方的端口与接收方的端口相同的话,甚至自己发的消息,自己都可以收到。这就很尴尬了,也就是说我们既要剔除自己发给自己的消息,也得区分不同手机发来的消息,这个时候就理应有一个“用户”的概念。

创建 User 对象,有哪些属性可以看自己的业务,本文的例子就有 ip、imei、以及 softversion。

    /**
     * 创建本地用户信息
     */
    private void createUser() {
        if (localUser == null) {
            localUser = new Users();
        }
        if (remoteUser == null) {
            remoteUser = new Users();
        }

        localUser.setImei(DeviceUtil.getDeviceId(mContext));
        localUser.setSoftVersion(DeviceUtil.getPackageVersionCode(mContext));

        if (WifiUtil.getInstance(mContext).isWifiApEnabled()) {// 判断当前是否是开启热点方
            localUser.setIp("192.168.43.1");
        } else {// 当前是开启 wifi 方
            localUser.setIp(WifiUtil.getInstance(mContext).getLocalIPAddress());
            remoteUser.setIp(WifiUtil.getInstance(mContext).getServerIPAddress());
        }
    }
    /**
     * <p><b>IMEI.</b></p> Returns the unique device ID, for example, the IMEI for GSM and the MEID
     * or ESN for CDMA phones. Return null if device ID is not available.
     * <p>
     * Requires Permission: READ_PHONE_STATE
     *
     * @param context
     * @return
     */
    public synchronized static String getDeviceId(Context context) {
        if (context == null) {
            return "";
        }

        String imei = "";

        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm == null || TextUtils.isEmpty(tm.getDeviceId())) {
                // 双卡双待需要通过phone1和phone2获取imei,默认取phone1的imei。
                tm = (TelephonyManager) context.getSystemService("phone1");
            }

            if (tm != null) {
                imei = tm.getDeviceId();
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        }


        return imei;
    }

这里就不将所有的代码展开来看了。如果有了手机的 imei 号,那很容易就可以来做身份的区分,你既可以区分不同的发送方,也可以剔除掉自己发给自己的消息。当然如果需要更多的信息,可以按照自己的业务区分,将这些信息作为发送的 messge,通过 Socket 发送。

写在后面:
到现在开始本文的大部分内容都已经介绍完成,有的同学可能会发问,你要用一个心跳来维持一个假的“长连接”,使用起来比较麻烦,而且还可能忍受 UDP 造成的丢包的痛苦,为什么不选择 TCP 呢?问得好,其实这个版本是当时做的第一个版本,之后就使用 TCP+UDP 的方式来完成这个模块了,下一篇文章再来看看加上 TCP 的改进版吧。

本文例子的所有代码在这里:

github 连接在这里 UDPSocketDemo

android手机与服务器基于UDP协议的通信 由于第一次写博客,所以肯定 阅读详情

相关推荐

超低价SDIO wifi模组 支持android (安卓) linux

超低价的SDIO wifi模组。支持android (安卓) linux   提供技术支持。 HLWF‐SD63 WIFI 通信模块 目录 1. 功能简介 .....................................................................................................................

yang55555ang的专栏 7253

Android 简单UDP通信框架(Kotlin)

使用说明 UDPManager是一个静态工具类。复制粘贴进去就可以使用。 使用前初始化: 1.通过UDPManager.init(port:Int)进行初始化。(默认本地端口为12306,可通过port参数修改) 2.通过UDPManager.setIPandPort(dstIP:String,dstPort:Int)设置目的IP和目的端口号。 使用时: 1.作为客户端: 使用sendMsg()...

花里胡哨 3319

全球网络对讲机Android Studio源码项目实战(含完整通信模块)

在中定义专用构建类型,用于开启详细日志与性能监控:android {prod {dev {生成的将包含:此机制使得在不同环境中动态调整编码参数成为可能,例如在开发版中启用高频采样率日志记录,而在生产环境中关闭以节省资源。便于统一过滤日志输出。为便于解析与路由,定义轻量级二进制协议头:字段长度(字节)描述2固定值0xABCD,标识协议起始10x01=语音包, 0x02=心跳, 0x03=控制命令1。

weixin_34547628的博客 932

android udp 框架,Android Network Protocol Stack

Android Network Protocol StackContains Udp Stack, Tcp Stack and Http Stack. A simple application framework.Udp StackWhen send request, the protocol stack will add two bytes at the beginning of the bus...

weixin_29313547的博客 470

Android平台UDP文本通信实践教程

在Android项目中,网络通信模块通常是应用与服务器进行数据交互的核心组件。对于一个结构良好的项目,这个模块需要有良好的设计,以便于维护和扩展。以下是网络通信模块设计的一些关键点。

weixin_30336531的博客 947

海康/大华设备如何接入GB28181平台?最新2022版互联避坑指南

本文详细解析了海康/大华设备接入GB28181平台的最新2022版互联避坑指南,涵盖参数配置、实时视音频点播协议交互及典型故障排查。重点介绍了GB/T28181-2022标准下的设备编码规范、SIP服务器配置及媒体流保活机制,帮助工程团队高效解决设备离线和媒体流中断等问题。

weixin_30733003的博客 686

Android网络应用学习笔记(二)引入多线程实现简单C/S聊天室应用

参考自《疯狂Android讲义》。 在实际情况下,客户端通常不止一个,不能让一个客户端一直占用服务器,所以服务器应该为每个客户端单独启动一条线程负责通信。而在Android客户端,为了避免让通信阻塞UI界面,应该为通信单独启动一条线程。事实上,Android平台早已不允许在UI线程中直接建立网络连接了。 事先说明,本项目只能用于局域网通信。 下面看代码。 1.服务器端实现代码 思路...

weixin_44390344的博客 537

安装VMware,出现没有虚拟网络适配器的问题

安装VMware,出现没有虚拟网络适配器的问题

Young_Harry的博客 1万+

UDP 理解

只是在校验和的计算过程中会被使用到,伪首部主要来自于运载UDP报文的IP数据报首部,将源IP地址和目的IP地址加入到校验和的计算中可以验证用户数据报是否已经到达正确的终点。伪首部完全是虚拟的,它并不会和用户数据报一起被发送出去。这里需要指出的一点是,udp头部大小为8字节。

baidu_16370559的博客 2818

ERA5 数据集下载(2025最新 可运行)

众所周知,ERA5数据集经过了更新,尤其是在API访问和下载方式上发生了变化。2025年版的ERA5数据集为气象研究人员提供了更高质量的历史气象数据。本文将介绍如何通过新的API接口下载最新的ERA5数据集。

m0_72141699的博客 3591

从零开始学习CANoe(六)—— CAPL 测试节点

创建CAPL Test Module的两种方式

蚂蚁小兵 1万+

在Android上,一个完整的UDP通信模块应该是怎样的?

CP与UDP差异对比分析 在这篇文章中,在可靠性、数据发送、适用场景等多个方面分析了二者的区别。而本文的目的是想给大家介绍下在 Android 设备上,一个手机通过热点连接另一个手机。这种场景下,完整的 UDP 通信模块应该考虑哪些方面,又应该如何优化,如何避开一些坑呢? UDP 在 Java 中的使用 我们都知道,开发一个 Android 应用程序,...

weixin_34232744的博客 154

YOLO26涨点改进 | 细节涨点篇 | 源自SCI一区 | YOLO26引入HWD小波下采样模块,而不会显著增加计算开销,(适合小目标分割任务、小目标检测任务)

本文提出了一种基于Haar小波变换的下采样模块HWD,用于改进YOLO26目标检测性能。HWD模块通过小波变换降低特征图分辨率,同时将空间信息编码到通道维度,有效保留了关键信息。相比传统下采样方法,HWD能显著减少信息不确定性,提升小目标检测精度。实验表明,该模块可无缝集成到CNN架构中,不增加计算开销。文章详细介绍了HWD的实现原理、代码结构以及在YOLO26中的集成方法,并提供了两种改进版yaml配置文件。该创新模块已在多种数据集上验证有效,特别适合语义分割和目标检测任务。

Ai缝合怪、助力小伙伴高效发论文 401

Android 一套完整的 Socket 解决方案

Android 一套完整的 Socket 解决方案项目地址,喜欢点一个 star:AndroidSocket写在前面:在上上周的时候,写了一篇文章:在 Android 上,一个完整的 UDP 通信模块应该是怎样的?文中介绍了在 Android 端,一个完整的 UDP 模块应该考虑哪些方面。当然了文中最后也提到了,UDP 的使用本身就有一些局限性,比如发送数据的大小有限制,属于不可靠协议,可能丢包。而

MeloDev的博客 2866

67、全球导航卫星系统授时弹性分析与建议

本文分析了全球导航卫星系统(GNSS)在授时过程中面临的问题,包括系统自身异常和外部干扰欺骗,并探讨了提升授时弹性的关键技术与解决方案。文章介绍了美国、欧洲及中国在弹性授时系统建设方面的进展,重点剖析了高精度原子钟、时间同步、干扰检测与识别等核心技术,提出了GNSS与其他授时系统互补的集成化发展路径。最后展望了未来授时系统向更高精度、更强弹性、更广应用的发展趋势,为构建安全可靠的国家授时体系提供参考。

corn8的博客 185

ACC自适应巡航系统

ACC自适应巡航系统可在高速驾驶情况下,自动控制纵向跟车距离,减轻驾驶员的工作量。该功能主要依靠安装在车辆前挡风玻璃上的摄像头和布置在格栅附近的雷达进行融合实现。

未知艺术家的博客 203

UnityNetWork:一套完整的Unity的socket网络通信模块

UnityNetWork:一套完整的Unity的socket网络通信模块 去发现同类优质开源项目:https://gitcode.com/ UnityNetWork 是一套专为Unity开发设计的socket网络通信模块。它为开发者提供了一个高效、稳定且易于集成的网络通信解决方案,适用于各种需要网络交互的Unity项目。 此模块具有以下特点: 跨平台兼容:支持Windows、MacOS、Linu...

gitblog_06723的博客 726

基于 transformer、lstm、LSTM多特征的交通流量预测 完整数据代码 超全项目 本科硕士毕设卓卓有余

基于 transformer、lstm、LSTM多特征的交通流量预测 完整数据代码 超全项目 本科硕士毕设卓卓有余

4655

android 组态软件,Livzenwex安卓版组态软件

力臻智合(Livzenwex)分布式组态软件安卓版解决方案,主要为运行安卓系统的嵌入式HMI设备(如平板电脑等)提供应用软件支持。力臻智合(Livzenwex)安卓版基于六子方的人机交互系统,并根据安卓系统的特点进行剪裁。用户使用由力臻智合(Livzenwex)安卓版提供的工具在Windows平台上制作工程,完成后下载到嵌入式设备中(力臻智合安卓版的运行环境需预先安装,且已经运行)运行。功能强大且...

weixin_39531374的博客 4379

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

告别广告烦恼:5分钟用Kotlin实现纯净版安卓网络调试工具(含BLE动态UUID获取技巧)

本文手把手教你用Kotlin快速打造一款纯净无广告的安卓网络调试工具。核心功能覆盖TCP、UDP、经典蓝牙和低功耗蓝牙通信,并重点详解了BLE开发中动态UUID的获取技巧,助你高效调试智能硬件,摆脱臃肿第三方工具的困扰。

white的博客 141

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

低功耗Air724UG模组软件指南:UDP示例来啦~建议收藏

在物联网(IoT)设备的开发中,低功耗和高效的数据传输是关键因素。Air724UG模组作为一款功能强大的无线通信模块,提供了多种协议支持,其中包括用户数据报协议(UDP)。本文将介绍如何在Air724UG模组中实现UDP通信,并提供示例代码供开发者参考。

ChenQuDe的博客 669

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Proxmark3与Android:USB OTG连接客户端开发

还在为RFID测试需要携带笔记本电脑而烦恼?一文解决移动端RFID分析难题!读完本文你将掌握: - Android设备通过USB OTG连接Proxmark3的两种方法 - TCP/UDP桥接技术的实现原理 - 客户端通信架构和开发要点 - 移动端RFID分析的完整解决方案 ## 为什么需要Android客户端? 传统Proxmark3使用依赖PC环境,限制了现场应用的灵活性。Android

gitblog_00165的博客 538

安卓系统组态软件_力臻智合分布式组态软件安卓版解决方案

力臻智合分布式组态软件安卓版解决方案,主要为运行安卓系统的嵌入式HMI设备(如平板电脑等)提供应用软件支持。力臻智合安卓版基于纵横思维的力臻智合系统,并根据安卓系统的特点进行剪裁。用户使用由力臻智合安卓版提供的工具在Windows平台上制作工程,完成后下载到嵌入式设备中(力臻智合安卓版的运行环境需预先安装,且已经运行)运行。功能强大且易于使用力臻智合分布式组态软件安卓版解决方案是原生的安卓应用程序...

weixin_35219482的博客 1332

安卓外置gps虚拟定位模块_通信模块结合GPS对时和定位功能,助力智能电网实现联网管控...

在智能电网逐渐普及的当下,传统人工巡视存在的人力成本高、效率低、作业难度大等问题不断催生旧有工作方式的改革。湖南供电局在综合考量了全省目前的线路结构、终端部署等情况后,于近日提出工作指导,将陆续推进电力设备安装GPS模块,湖南省各地电力线路及电力设备实现联网管控。“以前设备发生故障,需要人力寻找故障点,速度慢,耗时久,查找到的位置往往还不准确。”一位工作人员这样介绍现场情况。四信响应当地...

weixin_39867208的博客 2289
上一篇: TCP与UDP差异对比分析
下一篇: 这一年半以来,关于 Android,我都写了些什么?(一)
MeloDev
博客等级 码龄11年 93粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值