Android Framework 常见解决方案(20)UDP广播无效问题

这篇具有很好参考价值的文章主要介绍了Android Framework 常见解决方案(20)UDP广播无效问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 现象描述和原理解读

该问题同时存在于android App和Framework系统中。最终效果是在Android系统中直接使用UDP广播无效,有意思的是有的android系统可以,有的Android 系统不行。然而该部分代码自己在Linux上测试时是有效的,代码不变,只是简单的编译移植过来就变得莫名其妙的不行了,头还真是大的不行。

UDP广播接收端的关键实现程序如下所示:

#include <iostream>
#include <string>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

const int UDP_PORT = 19662;

int main() {
    int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd == -1) {
        std::cerr << "Failed to create socket" << std::endl;
        return 1;
    }

    struct sockaddr_in local_address{};
    local_address.sin_family = AF_INET;
    local_address.sin_addr.s_addr = INADDR_ANY;
    local_address.sin_port = htons(UDP_PORT);

    if (bind(socket_fd, (struct sockaddr*)&local_address, sizeof(local_address)) == -1) {
        std::cerr << "Failed to bind socket" << std::endl;
        close(socket_fd);
        return 1;
    }

    std::cout << "Listening for UDP broadcast on port " << UDP_PORT << std::endl;

    char buffer[1024];
    struct sockaddr_in sender_address{};
    socklen_t sender_address_length = sizeof(sender_address);

    while (true) {
        ssize_t bytes_received = recvfrom(socket_fd, buffer, sizeof(buffer), 0,
                                          (struct sockaddr*)&sender_address, &sender_address_length);
        if (bytes_received == -1) {
            std::cerr << "Error receiving data" << std::endl;
            close(socket_fd);
            return 1;
        }

        std::string received_message(buffer, bytes_received);
        std::cout << "Received message from " << inet_ntoa(sender_address.sin_addr)
                  << ": " << received_message << std::endl;
    }

    close(socket_fd);
    return 0;
}

UDP广播发送端测试程序如下:

#include <iostream>
#include <string>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

const int UDP_PORT = 19662;
const std::string UDP_BROADCAST_ADDRESS = "192.168.1.255";

int main() {
    int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_fd == -1) {
        std::cerr << "Failed to create socket" << std::endl;
        return 1;
    }

    int broadcast_enable = 1;
    if (setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) == -1) {
        std::cerr << "Failed to enable broadcast" << std::endl;
        close(socket_fd);
        return 1;
    }

    struct sockaddr_in target_address{};
    target_address.sin_family = AF_INET;
    target_address.sin_port = htons(UDP_PORT);
    if (inet_pton(AF_INET, UDP_BROADCAST_ADDRESS.c_str(), &target_address.sin_addr) <= 0) {
        std::cerr << "Invalid address" << std::endl;
        close(socket_fd);
        return 1;
    }

    std::string message = "Hello UDP Broadcast!";
    ssize_t bytes_sent = sendto(socket_fd, message.c_str(), message.size(), 0,
                                (struct sockaddr*)&target_address, sizeof(target_address));
    if (bytes_sent == -1) {
        std::cerr << "Failed to send data" << std::endl;
        close(socket_fd);
        return 1;
    }

    std::cout << "Sent broadcast message: " << message << std::endl;

    close(socket_fd);
    return 0;
}

在移植到android的过程中实际上是使用android走JNI调用C++的方式来使用,这里就不详述了。

最后分析,发现,果然是android的问题。因为在 移动端 Android 系统中,使用 UDP 广播可能会引发一些耗电的问题,因为 UDP 广播需要 Wi-Fi 连接保持在活动状态,以便能够发送和接收数据包。为了避免在应用程序使用 UDP 广播时造成不必要的电池消耗,开发者可以考虑使用 Wi-Fi 锁来控制 Wi-Fi 连接的状态。

Wi-Fi 锁是 Android 提供的一种机制,允许应用程序在需要时保持 Wi-Fi 连接处于活动状态,而不会由于系统的网络管理策略而被关闭或断开连接。使用 Wi-Fi 锁,应用程序可以确保在需要进行网络通信时,Wi-Fi 连接一直保持活跃,从而避免了频繁的连接和断开过程,这有助于降低耗电量。

2 修改方案(Android All)

Wi-Fi锁的获取和释放源码如下所示:

import android.content.Context;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;

public class WifiLockManager {
    private WifiLock wifiLock;
    private WifiManager wifiManager;

    public WifiLockManager(Context context) {
        wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWifiLock");
    }

    //获取锁
    public void acquireWifiLock() {
        wifiLock.acquire();
    }

    //释放锁
    public void releaseWifiLock() {
        if (wifiLock.isHeld()) {
            wifiLock.release();
        }
    }
}

这样在UDP广播时就不会出现连不上的情况了。实际上Wi-Fi 锁机制从 Android 1.0 版本就存在,但是随着不同版本的 Android 系统的发布和演变,该机制可能会有一些变化和改进。

具体的行为和影响因 Android 版本和设备厂商而异。在早期的 Android 版本中,Wi-Fi 锁主要用于控制 Wi-Fi 连接的休眠策略,以防止在连接处于活动状态时进入省电模式。然而,随着 Android 版本的更新,系统对网络管理策略进行了多次改进,旨在更好地平衡性能和电池寿命,因此 Wi-Fi 锁的影响和需求可能会因 Android 版本的变化而变化。

另外,不同的硬件厂商可能会在其定制的 Android 版本中对网络管理和电池优化策略进行调整。这意味着在某些设备上,Wi-Fi 锁的行为可能会受到硬件和厂商定制的影响,因此才会出现有的设备能直接广播而有的需要wifi锁这样的情况。文章来源地址https://www.toymoban.com/news/detail-659517.html

到了这里,关于Android Framework 常见解决方案(20)UDP广播无效问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VS2022迁移VS2019项目遇到的.Net Framework 引用程序集问题解决方案

    在GitHub上发现TrafficMonitor的开源代码,想要自己过一遍这个项目 在VS2022上面打开出现了MSB3644错误,打开微软 “找不到项目所请求 .NET 版本的 .NET 引用程序集时,会发生此错误。 发生此问题的原因可能是项目文件存在问题,它所请求的版本无法识别或未安装;也可能是安装问

    2024年02月06日
    浏览(63)
  • 【解决方案】找不到依赖 “@tarojs/plugin-framework-react“,请先在项目中安装

    导入微信小程序项目,执行yarn build:weapp 或者npm run build:weapp后报错如下: 👽 Taro v3.5.12 找不到依赖 \\\"@tarojs/plugin-framework-react\\\",请先在项目中安装 报错原因是Taro的版本号和其他插件版本号不匹配。 解决方法是终端执行以下代码,添加或更新插件。

    2024年02月12日
    浏览(37)
  • Python网络编程之udp编程、黏包以及解决方案、tcpserver

    Hello,大家好我是景天,上一章我们聊打了Python网络编程,详细介绍了基于TCP协议的编程。TCP协议,每次都要经过三次握手才能建立连接,效率比较低。有没有更快的数据传输方式呢? 今天我们就一起谈谈UDP。 udp与tcp基本一样,就是协议类型改下即可 udp第一次只能客户端发

    2024年02月19日
    浏览(23)
  • 电脑服务器离线安装.net framework 3.5解决方案(错误:0x8024402c )(如何确定当前系统是否安装NET Framework 3.5)

            日常服务的搭建或多或少都会有需要到NET Framework 3.5的微软程序运行框架,本次介绍几种不同的安装方式主要解决运行在Windows 2012 以上的操作系统的服务。         .NET Framework是微软公司推出的程序运行框架,主要包含运行库和公共语言集,3.5是版本号, 目前最

    2024年02月19日
    浏览(30)
  • ubuntu20.04网络问题以及解决方案

    参考:https://blog.51cto.com/u_204222/2465609 https://blog.csdn.net/qq_42265170/article/details/123640669 原始是在虚拟机中切换网络连接方式(桥接和NAT), 解决方法 :临时方法sudo dhclient ens33,强行吊起来ens33,吊起来当然也有可能只有mac地址没ip地址。 最终的解决方法,目的是默认打开网络管理

    2024年01月16日
    浏览(31)
  • Java常见Bug解决方案

    刚开始学习Java语言的小伙伴, 很可能被各种各样的程序bug搞得焦头烂额, 甚至被劝退。别怕,健哥将手把手带你了解Java中的异常体系, 如何识别Bug以及如何解决Bug。 让我们先来了解下Java中的异常分类, 如下图: Java中的异常分为Error错误和Exception异常两大类 Error错误 : 一般所有

    2024年02月13日
    浏览(25)
  • 冷启问题目前常见解决方案

    随机冷启 个性化冷启 冷启动保量 冷启动保量,保证每个item曝光的次数一样,实时统计已曝光的次数和要曝光的次数 冷启动结束过滤,如果需曝光的量越大,且越接近冷启结束时间,得分越高,被曝光的概率越大 爬坡保量 实时统计曝光、点击、ctr;ctr越高,曝光越少,得分

    2024年02月11日
    浏览(33)
  • 常见的跨域解决方案

    常见的跨域解决方案: 跨域问题可以分为两种情况: 前端跨域和后端跨域 。以下是针对这两种情况的跨域解决方案: 前端跨域解决方案: JSONP: 适用于前端向不同域名下的服务器请求数据,通过添加回调函数名称来实现跨域数据获取。 CORS: 当前端向服务器请求数据时,

    2024年02月12日
    浏览(30)
  • 正则常见问题及解决方案

    使用正则处理问题的基本思路。有一些方法比较固定,比如将问题分解成多个小问题,每个小问题见招拆招:某个位置上可能有多个字符的话,就⽤字符组。某个位置上有多个字符串的话,就⽤多选结构。出现的次数不确定的话,就⽤量词。对出现的位置有要求的话,就⽤锚

    2024年02月10日
    浏览(47)
  • Hadoop常见异常及其解决方案

    1、Shell$ExitCodeException 现象:运行hadoop job时出现如下异常: 14/07/09 14:42:50 INFO mapreduce.Job: Task Id : attempt_1404886826875_0007_m_000000_1, Status : FAILED Exception from container-launch: org.apache.hadoop.util.Shell E x i t C o d e E x c e p t i o n : o r g . a p a c h e . h a d o o p . u t i l . S h e l l ExitCodeException: org.ap

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包