【问题标题】:Android SSDP Service DiscoveryAndroid SSDP 服务发现
【发布时间】:2025-12-01 13:05:01
【问题描述】:

我正在实现一个 java 程序,它使用 SSDP 发现扫描我拥有的一些智能设备。我使用的代码仅检测到 10 个连接到我的本地网络的设备中的 2 个。我无法理解的原因是。

我的问题是,为什么我无法获取本地网络中的所有设备。

这是我正在使用的代码

static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT;
static final String MAN = "Man: \"ssdp:discover\"";
 static final String NEWLINE = "\r\n";

int mMX = 10;    /* 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();
}

下面是几个常量

 /* 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: upnp:rootdevice";
public static final String ST_ContentDirectory = "ST: urn:schemas-upnp-org:service:ContentDirectory:1";
public static final String ST_ALL="ST: ssdp:all";
public static final String ST_Media="ST:urn:schemas-upnp-org:device:MediaRenderer: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";

主类

public class SSDPSocket {
SocketAddress mSSDPMulticastGroup;
MulticastSocket mSSDPSocket;

public SSDPSocket() throws IOException {
    InetAddress localInAddress = InetAddress.getLocalHost();
    System.out.println("Local address: " + localInAddress.getHostAddress());

    mSSDPMulticastGroup = new InetSocketAddress(SSDP.ADDRESS, SSDP.PORT);
    mSSDPSocket = new MulticastSocket(new InetSocketAddress(localInAddress,
            0));

    NetworkInterface netIf = NetworkInterface
            .getByInetAddress(localInAddress);
    mSSDPSocket.joinGroup(mSSDPMulticastGroup, netIf);
}

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

    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();
    }
}

/* For test purpose */
public static void main(String[] args) {

    SSDPSearchMsg search = new SSDPSearchMsg(SSDP.ST_Media);
    System.out.println(search.toString());

    SSDPSocket sock;
    try {
        sock = new SSDPSocket();
        sock.send(search.toString());

        while (true) {
            DatagramPacket dp = sock.receive();
            String c = new String(dp.getData());
            System.out.println(c);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
    }
}

谁能为这个问题提出一个解决方案?

【问题讨论】:

  • 如果您有另一个 SSDP 客户端获得 10 个回复,而您的客户端获得 2 个回复,则应该很容易获得网络流量转储并查看两种情况的不同之处(例如,参见 Wireshark) .
  • 另外,您正在搜索 MediaRenderer 设备:您确定您的网络中有 10 个 mediarenderer?
  • 我什至尝试过使用 ssdp:all,但我仍然只能得到少数设备。
  • 当我在 Linux 系统中运行 gssdp 命令时,我能够获取连接到我的网络的所有设备。它可以检测 Windows 系统、Linux、Ubuntu 和飞利浦 Hue、Belkin wemo 等智能设备。

标签: java ssdp


【解决方案1】:

我刚刚开发了一个 SSDP Java 客户端,并仔细研究了规范。

您缺少“MX”标头。如果未设置标头 MX,SSDP 服务“应该”不会响应您的请求。 因此,请尝试添加一个“MX: 1”标题并查看它的位置。

Schneider database 对这个问题很有帮助。

另外,如果您还在尝试使用 ssdp client,可以查看它。

【讨论】: