Android通过WiFi Direct连树莓派时DatagramSocket无法接收UDP数据包
排查修复方案
优先级从高到低的验证步骤
- 1. 排查树莓派防火墙拦截
树莓派默认iptables规则大概率会拦截WiFi Direct虚拟接口的UDP流量,先临时清空防火墙规则验证:sudo iptables -F
若测试后Android端成功收到回包,添加永久放行8988端口UDP的规则即可:sudo iptables -A INPUT -p udp --dport 8988 -j ACCEPT sudo iptables -A OUTPUT -p udp --sport 8988 -j ACCEPT # Debian/Ubuntu系系统保存规则命令 sudo netfilter-persistent save - 2. 移除C++代码中
sendto的MSG_CONFIRM标记
你当前代码里sendto使用的MSG_CONFIRM是Linux特有的链路层优化标记,部分WiFi Direct网卡驱动对该标记兼容异常,会导致数据包未实际发送到无线接口。修改sendto的flags参数为0:int sent = sendto(sock_fd, CONFIRM_CONNECTION_MSG.c_str(), CONFIRM_CONNECTION_MSG.length(), 0, (const struct sockaddr*) &client_addr, len); - 3. Android端显式绑定Socket到WiFi Direct网络
Android多网络共存场景下(如同时连接普通WiFi和WiFi Direct),系统默认不会将Socket绑定到WiFi Direct的p2p接口,导致无法接收对应接口的数据包。创建DatagramSocket后添加绑定逻辑:socket = new DatagramSocket(PORT); // 此处p2pNetwork为WiFi Direct连接对应的Network对象,可通过WifiP2pManager回调或ConnectivityManager过滤P2P类型网络获取 p2pNetwork.bindSocket(socket); socket.setSoTimeout(RECEIVE_TIMEOUT_MS); - 4. 基础信息校验
先确认树莓派日志中打印的Client Addr是否为Android端的实际IP(一般为192.168.4.xxx段),Client Port是否为8988,避免IP/端口识别错误。 - 5. 抓包辅助定位
树莓派端用tcpdump抓WiFi Direct接口的流量确认包是否实际发出:
Android端可通过自带的网络调试工具抓包,确认数据包是否到达设备。# 先查询WiFi Direct对应的接口名,一般为p2p-wlan0-0 ip a # 抓对应接口8988端口的UDP包 sudo tcpdump -i p2p-wlan0-0 udp port 8988
内容的提问来源于stack exchange,提问作者Cade Reynoldson
相关产品推荐
相关产品推荐

