未收到或延迟收到 UPnP 事件

UPnP events not received or received late

我一直在研究一个简单的 UPnP 客户端实现,但我在接收事件时遇到了问题。为了尝试找出我发送的消息中的错误,我使用 CLing(这是一个很棒的库,但它依赖于 Java 1.5,而我只能访问 1.4)测试了我的用例,它运行良好,但我在它的消息和我的消息之间找不到任何有意义的区别。

我正在订阅 /MediaRenderer/AVTransport/Event 事件,正在测试是否可以获得最新的 TransportState。

这是我的测试代码:

private static final String PLAYER_IP = "192.168.10.101";

public static void main(String[] args) throws Exception {
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(null);

    System.out.println("Started server on port " + serverSocket.getLocalPort() + ", ready for connections");

    sendSubscription(serverSocket.getLocalPort());

    while (!serverSocket.isClosed())
        handle(serverSocket.accept());
}

private static void sendSubscription(int port) throws Exception {
    Socket socket = new Socket(PLAYER_IP, 1400);
    PrintWriter out = new PrintWriter(socket.getOutputStream());

    out.print("SUBSCRIBE /MediaRenderer/AVTransport/Event HTTP/1.1\r\n"
            + "HOST: " + PLAYER_IP + ":1400\r\n"
            + "USER-AGENT: MacOSX/10.12.4 UPnP/1.0 MyApp/0.1\r\n"
            + "CALLBACK: <http://" + InetAddress.getLocalHost().getHostAddress() + ":" + port + "/dev>\r\n"
            + "NT: upnp:event\r\n"
            + "TIMEOUT: Second-3600\r\n"
            + "\r\n");
    out.flush();

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    String line;
    while ((line = in.readLine()) != null)
        System.out.println(line);
}

private static void handle(final Socket clientSocket) {
    new Thread(new Runnable() {
        public void run() {
            System.out.println();
            System.out.println("Request incoming " + new Date());
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    System.out.println(line);
                    if (line.contains("TransportState"))
                        System.out.println("TransportState: " + line.substring(line.indexOf("TransportState") + 25));
                }
            }
            catch (IOException e) {}

            try {
                PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
                out.print("HTTP/1.1 200 OK\r\n"
                        + "Server: MacOSX/10.12.4 UPnP/1.0 MyApp/0.1\r\n"
                        + "Connection: close\r\n"
                        + "\r\n");
                out.flush();
            }
            catch (IOException e) {}
        }
    }).start();
}

它发送一个订阅请求,然后不断地读取通知。您可能会注意到我没有使用任何库来做任何事情,但由于偏执狂,我已经删除了它们,直到我可以使这个基本用例正常工作。

结果是,当我使用我的 phone 例如 play/stop 一个曲目或广播电台时,事件并不总是到达,而当它们到达时,它们通常很晚.这种行为对于我的应用程序是一致的,而不是对于 CLing,所以我得出结论,我可以排除我的网络。我已经 Wireshark 了我的应用程序和 CLing 之间的区别,订阅消息几乎相同(我什至尝试了 CLing 发送的确切消息)。两个应用程序 运行 在同一台 PC 上,都在同一 JVM 上。

根据 UPnP 规范,媒体渲染器会在订阅后立即发送通知,通知总是会到达,我没有看到任何意外的延迟。

这对我来说很奇怪,我不知道接下来可以尝试什么。如果有人知道此问题的原因可能是什么,我将永远感激不已!

问题在于 HTTP 服务器实现在某些情况下不发送 HTTP 响应代码。媒体渲染器在收到 HTTP 200 响应之前不会发送下一个事件。 Java 1.4 似乎是一个很好的轻量级 HTTP 服务器很难找到。