gpt4 book ai didi

java - 无法使用 SSDP 接收正确的 UDP 数据包

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:57 26 4
gpt4 key购买 nike

我正在尝试在我的安卓应用中实现一个非常简单的 SSDP 功能 from here .

我的应用程序毫无问题地向广播地址发送了一些包含相关 M-SEARCH 消息的 UDP 数据包。问题是,我应该从其他运行 UPNP 服务器的设备得到正确的响应。出于某种原因,我只收到与我从 Android 设备发送的完全相同的数据包。

主 Activity .java

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wm.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();

setContentView(R.layout.activity_main);

((Button)this.findViewById(R.id.btnSendSSDPSearch)).setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSendSSDPSearch:
new Thread(new Runnable() {

@Override
public void run() {
SendMSearchMessage();
}
}).start();

default:
break;
}
}

private void SendMSearchMessage() {

SSDPSearchMsg searchContentDirectory = new SSDPSearchMsg(SSDPConstants.ST_ContentDirectory);
SSDPSearchMsg searchAVTransport = new SSDPSearchMsg(SSDPConstants.ST_AVTransport);
SSDPSearchMsg searchProduct = new SSDPSearchMsg(SSDPConstants.ST_Product);

SSDPSocket sock;
try {
sock = new SSDPSocket();
for (int i = 0; i < 2; i++) {
sock.send(searchContentDirectory.toString());
sock.send(searchAVTransport.toString());
sock.send(searchProduct.toString());
}

while (true) {
DatagramPacket dp = sock.receive(); //Here, I only receive the same packets I initially sent above
String c = new String(dp.getData());
System.out.println(c);
}
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("M-SEARCH", e.getMessage());

}

SSDPSocket.java真正完成UDP包传输

public class SSDPSocket {
SocketAddress mSSDPMulticastGroup;
MulticastSocket mSSDPSocket;
InetAddress broadcastAddress;

public SSDPSocket() throws IOException {
mSSDPSocket = new MulticastSocket(55325); //Bind some random port for receiving datagram
broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS);
mSSDPSocket.joinGroup(broadcastAddress);
}

/* Used to send SSDP packet */
public void send(String data) throws IOException {
DatagramPacket dp = new DatagramPacket(data.getBytes(), data.length(),
broadcastAddress,SSDPConstants.PORT);

mSSDPSocket.send(dp);
}

/* Used to receive SSDP packet */
public DatagramPacket receive() throws IOException {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);

mSSDPSocket.receive(dp);

return dp;
}

public void close() {
if (mSSDPSocket != null) {
mSSDPSocket.close();
}
}
}

SSDPSearchMsg.java 用于构造SSDP广播字符串(可能与我遇到的问题无关,但以防万一)

public class SSDPSearchMsg {
static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT;
static final String MAN = "Man:ssdp:discover";
static final String NEWLINE = System.getProperty("line.separator");

int mMX = 3; /* seconds to delay response */
String mST; /* Search target */

public SSDPSearchMsg(String ST) {
mST = ST;
}

public int getmMX() {
return mMX;
}

public void setmMX(int mMX) {
this.mMX = mMX;
}

public String getmST() {
return mST;
}

public void setmST(String mST) {
this.mST = mST;
}

@Override
public String toString() {
StringBuilder content = new StringBuilder();

content.append(SSDP.SL_MSEARCH).append(NEWLINE);
content.append(HOST).append(NEWLINE);
content.append(MAN).append(NEWLINE);
content.append(mST).append(NEWLINE);
content.append("MX:" + mMX).append(NEWLINE);
content.append(NEWLINE);

return content.toString();
}
}

SSDPConstants.java

public class SSDPConstants {
/* New line definition */
public static final String NEWLINE = "\r\n";

public static final String ADDRESS = "239.255.255.250";
public static final int PORT = 1900;

/* Definitions of start line */
public static final String SL_NOTIFY = "NOTIFY * HTTP/1.1";
public static final String SL_MSEARCH = "M-SEARCH * HTTP/1.1";
public static final String SL_OK = "HTTP/1.1 200 OK";

/* Definitions of search targets */
public static final String ST_RootDevice = "St: rootdevice";
public static final String ST_ContentDirectory = "St: urn:schemas-upnp-org:service:ContentDirectory:1";
public static final String ST_AVTransport = "St: urn:schemas-upnp-org:service:AVTransport:1";
public static final String ST_Product = "St: urn:av-openhome-org:service:Product:1";

/* Definitions of notification sub type */
public static final String NTS_ALIVE = "NTS:ssdp:alive";
public static final String NTS_BYE = "NTS:ssdp:byebye";
public static final String NTS_UPDATE = "NTS:ssdp:update";
}

我还确保 list 包含相关权限:

 <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

我是在实际设备上测试应用程序,而不是在模拟器上。

如有任何帮助,我们将不胜感激。

根据评论编辑:

多播本身应该没有问题。我下载了一个名为 BubbleUPNP 的应用程序来测试 SSDP 功能。果然,wireshark 正确捕获了所有从手机发送到 SSDP 协议(protocol)中的广播地址的消息:

M-SEARCH * HTTP/1.1

Man: "ssdp:discover"

Mx: 3

Host: 239.255.255.250:1900

St: urn:schemas-upnp-org:service:AVTransport:1

和响应

HTTP/1.1 200 OK

ST:urn:schemas-upnp-org:service:ContentDirectory:1

USN:uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232::urn:schemas-upnp-org:service:ContentDirectory:1

Location:http://10.175.95.4:2869/upnphost/udhisapi.dll?content=uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232

OPT:"http://schemas.upnp.org/upnp/1/0/"; ns=01

01-NLS:05f3dd08b4b4b5aafa1fe983fa447f49

Cache-Control:max-age=900

Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0

是的,毫无疑问,这是一个实现问题。设备没有问题。

最佳答案

奇怪。我解决了这个问题,但我真的不确定是什么让它起作用。

以下是我所做的一些更改:

我没有分配固定端口,而是动态分配可用端口。

public class SSDPSocket {
SocketAddress mSSDPMulticastGroup;
MulticastSocket mSSDPSocket;
InetAddress broadcastAddress;

public SSDPSocket() throws IOException {

mSSDPSocket = new MulticastSocket();
broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS);
mSSDPSocket.joinGroup(broadcastAddress);
}
...
}

我还更改了 M-Search 消息结构,包括它的顺序。

public class SSDPSearchMsg {
static final String HOST = "Host: " + SSDPConstants.ADDRESS + ":" + SSDPConstants.PORT;
static final String MAN = "Man: \"ssdp:discover\"";
static final String NEWLINE = "\r\n";

int mMX = 3; /* seconds to delay response */
String mST; /* Search target */

public SSDPSearchMsg(String ST) {
mST = ST;
}

public int getmMX() {
return mMX;
}

public void setmMX(int mMX) {
this.mMX = mMX;
}

public String getmST() {
return mST;
}

public void setmST(String mST) {
this.mST = mST;
}

@Override
public String toString() {
StringBuilder content = new StringBuilder();

content.append(SSDPConstants.SL_MSEARCH).append(NEWLINE);
content.append(MAN).append(NEWLINE);
content.append("Mx: " + mMX).append(NEWLINE);
content.append(HOST).append(NEWLINE);
content.append(mST).append(NEWLINE);
content.append(NEWLINE);

return content.toString();
}
}

然后一切突然都正常了。为什么它有效超出我的范围。据我所知,我之前的实现遵循 SSDP 协议(protocol)。

关于java - 无法使用 SSDP 接收正确的 UDP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15743550/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com