Android开发板:局域网UDP通信 二维码
发表时间:2026-06-18 17:50 1. 方案概述 在工业控制、物联网网关、安防监控等场景中,Android 开发板与局域网服务器(或 PC)之间的数据交互对实时性要求极高。相较于 TCP,UDP 协议具有无连接、无握手开销、首部开销小等天然优势,是局域网内高速数据传输、设备发现(OSD/ONVIF 探测)的绝佳选择。 本方案提供了一个完整的 UDP 客户端 Demo,配合标准 PC 端测试软件,帮助您快速评估我司开发板的网络吞吐与低延迟特性。 2. Android 客户端核心实现 (生产级 Demo) Android 的网络操作必须在子线程中执行,且由于 Android 6.0+ 的权限管理,需要在 AndroidManifest.xml 中声明权限。 Step 1: 权限配置 (AndroidManifest.xml) <!-- 允许访问网络状态和进行 network 连接 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 如果需要支持 UDP 组播/广播,可选添加 --> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> Step 2: 核心通信类 UdpClientManager.java 这是一个完整的、开箱即用的 UDP 管理类,采用了线程池设计,避免频繁创建线程,且支持单例模式。 package com.example.udpdemo; import android.util.Log; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class UdpClientManager { private static final String TAG = "UdpClientManager";
private DatagramSocket mSocket; private ExecutorService mThreadPool; private boolean isListening = false; private OnUdpMessageListener mListener; public interface OnUdpMessageListener { void onMessageReceived(String message, String hostAddress, int port); void onError(Exception e); } public UdpClientManager(OnUdpMessageListener listener) { this.mListener = listener; this.mThreadPool = Executors.newFixedThreadPool(2); initSocket(); } private void initSocket() { try { if (mSocket == null || mSocket.isClosed()) { mSocket = new DatagramSocket(); Log.d(TAG, "UDP Socket 初始化成功, 本地端口: " + mSocket.getLocalPort()); } } catch (SocketException e) { Log.e(TAG, "Socket 初始化失败", e); if (mListener != null) mListener.onError(e); } } public void sendMessage(final String msg, final String destIp, final int destPort) { mThreadPool.execute(new Runnable() { @Override public void run() { try { initSocket(); byte[] bytes = msg.getBytes("UTF-8"); InetAddress address = InetAddress.getByName(destIp); DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, destPort); mSocket.send(packet); Log.d(TAG, "已发送数据到 " + destIp + ":" + destPort + " -> " + msg); } catch (UnknownHostException e) { Log.e(TAG, "未知主机 IP", e); } catch (IOException e) { Log.e(TAG, "发送 IO 异常", e); } } }); } public void startReceiveThread() { if (isListening) return; isListening = true;
mThreadPool.execute(new Runnable() { @Override public void run() { byte[] buffer = new byte[1024 * 2]; while (isListening) { try { initSocket(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length); Log.d(TAG, "开始阻塞监听来自 PC 的 UDP 回应..."); mSocket.receive(packet);
String recvStr = new String(packet.getData(), 0, packet.getLength(), "UTF-8"); String hostIP = packet.getAddress().getHostAddress(); int port = packet.getPort();
Log.d(TAG, "收到数据来自 [" + hostIP + ":" + port + "]: " + recvStr);
if (mListener != null) { mListener.onMessageReceived(recvStr, hostIP, port); } } catch (IOException e) { Log.e(TAG, "接收异常(可能 Socket 已关闭)", e); } } } }); } public void close() { isListening = false; if (mSocket != null && !mSocket.isClosed()) { mSocket.close(); mSocket = null; } if (mThreadPool != null && !mThreadPool.isShutdown()) { mThreadPool.shutdownNow(); } Log.d(TAG, "UDP 连接已关闭, 资源已释放"); } } Step 3: 在 MainActivity.java 中调用 在界面上放置两个输入框(IP 和内容)、一个“发送”按钮、一个文本框(显示接收内容)。 package com.example.udpdemo; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements UdpClientManager.OnUdpMessageListener { private EditText etTargetIp, etMessage; private TextView tvLog; private Button btnSend; private UdpClientManager udpManager; private final int TARGET_PORT = 8888; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etTargetIp = findViewById(R.id.et_target_ip); etMessage = findViewById(R.id.et_message); tvLog = findViewById(R.id.tv_log); btnSend = findViewById(R.id.btn_send); udpManager = new UdpClientManager(this); udpManager.startReceiveThread(); btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String ip = etTargetIp.getText().toString().trim(); String msg = etMessage.getText().toString(); udpManager.sendMessage(msg, ip, TARGET_PORT); } }); } @Override public void onMessageReceived(final String message, final String hostAddress, final int port) { runOnUiThread(new Runnable() { @Override public void run() { tvLog.append("\n收到 " + hostAddress + ":" + port + " -> " + message); } }); } @Override public void onError(Exception e) { runOnUiThread(new Runnable() { @Override public void run() { tvLog.append("\n发生错误: " + e.getMessage()); } }); } @Override protected void onDestroy() { super.onDestroy(); if (udpManager != null) { udpManager.close(); } } } 3. PC 服务端配置(如何配合测试) 为了让板子发送的 UDP 数据有去有回,PC 端需要运行一个 UDP 调试助手。无需客户自己写代码,推荐使用以下主流免安工具: 推荐软件:NetAssist (网络调试助手) 或 SSCOM 软件配置步骤: 1. 协议类型:选择 UDP。 2. 本地 IP 地址:选择您当前 PC 的局域网 IP(例如 192.168.1.100)。 3. 本地端口号:填入 8888(需与 Android 客户端代码中的目标端口一致)。 4. 点击 “连接” 或 “打开” 开始监听。 注意:测试前请确保 Android 开发板与 PC 连接在同一个路由器/交换机下(同网段),并检查 PC 的 Windows 防火墙,确保其允许该调试软件访问网络。 4. 联合调试闭环验证(5分钟测试指南) 1. 硬件准备:用网线将 Android 开发板 和 PC 接入同一交换机(或路由器),确保两端获取到同网段 IP。 2. PC端准备:打开 NetAssist,类型选 UDP,本地端口填 8888,点击“打开”。 3. 板子端运行:打开 Demo App,在目标 IP 输入框中填入 PC 的 IP,点击 “发送”。 4. 效果看点:板子发送后,PC 端 NetAssist 窗口立刻会收到板子传过来的字符串。在 PC 端 NetAssist 的“远程主机”栏填入板子的 IP 和随机生成的本地端口,点击发送,板子界面也将实时刷新显示接收到的内容。 5. 为什么选择我们的板子? 千兆级以太网原生支持:本板搭载原生网卡芯片,PHY 层物理层硬件优化,UDP 吞吐量接近理论物理极限,杜绝因硬件导致的丢包。 极低传输时延:精简的 Linux 内核/Android 系统网络栈定制,减少数据包从内核态到用户态的拷贝时间,非常适合工业高频通信。 全天候稳定性:支持 7×24 小时长时间大流量 UDP 压测不掉线,守护客户关键业务。 声明:此文为广州定昌电子小编辛苦码字原创编辑,部分素材来源于自家工厂及合作客户,网络分享,如有权利声明或内容有误,欢迎联系小编处理或更正(邮箱:91hui@163.com),欢迎你转载,务必请标明出处链接:https://www.gzdcsmt.com/sys-nd/4171.html
|
你的姓名 * 你的联系方式 * 你的公司名称 补充说明 提交 |