TL;DR:SSDP库未接收到数据报。Wireshark显示预期流量。
我正在使用安卓dlna库来支持安卓应用程序中的SSDP。目标是发现一个自定义的SSDP-enabled设备,获取其IP地址,然后对其进行RESTful API调用。这在iOS上运行良好,但我在Android上接收数据报时遇到了一些问题。
使用Wireshark,我可以确定SSDP搜索结束,设备返回状态为OK,但此循环从未通过receive()
方法:
SSDPSearchMsg search = new SSDPSearchMsg(SSDP.ST_ContentDirectory);
Log.e("SSDP", search.toString());
SSDPSocket sock = null;
try {
sock = new SSDPSocket();
sock.send(search.toString());
while (true) {
Log.e("SSDP", "Receive...");//only called once (stuck here)
DatagramPacket dp = sock.receive();
Log.e("SSDP", "Datagram Received with data " + new String(dp.getData()));
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
Log.e("SSDP", "Closing Socket");
if (sock != null)
sock.close();
}
这一切都是在AsyncTask
中完成的。我看到以下内容打印到logcat:
SSDP M-SEARCH * HTTP/1.1
SSDP Host:239.255.255.250:1900
SSDP Man:"ssdp:discover"
SSDP ST:urn:schemas-upnp-org:service:ContentDirectory:1
SSDP MX:3
SSDP
SSDP Receive...
Wireshark报告以下相关数据报:
Source Destination Protocol Length Info
---------------------------------------------------------------------------
192.168.1.7 239.255.255.250 SSDP 175 M-SEARCH * HTTP/1.1
192.168.1.1 192.168.1.7 SSDP 356 HTTP/1.1 200 OK
最后,我有以下清单权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
我在俯瞰什么?为什么我没有收到响应数据报?
我知道这是一个老问题,但它也让我绊倒了,所以也许这会帮助其他在这个问题上绊倒的人。如果你没有获得MulticastLock
,Android会过滤掉多播数据包,所以更新代码以获得MulticastLock
,并在完成后释放它。
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock lock = wifi.createMulticastLock("ssdp");
try {
lock.acquire();
sock = new SSDPSocket();
sock.send(search.toString());
while (true) {
Log.e("SSDP", "Receive...");//only called once (stuck here)
DatagramPacket dp = sock.receive();
Log.e("SSDP", "Datagram Received with data " + new String(dp.getData()));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
Log.e("SSDP", "Closing Socket");
if (sock != null)
sock.close();
if(lock.isHeld()) {
lock.release();
}
}
需要以下权限(已经在OP的清单文件中)--
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>