无法接收使用SSDP正确的UDP数据包 [英] Unable to receive proper UDP packets using SSDP

查看:2759
本文介绍了无法接收使用SSDP正确的UDP数据包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个非常简单的SSDP功能集成到我的Andr​​oid应用程序采取<一href="https://$c$c.google.com/p/android-dlna/source/browse/trunk/src/org/ray/?r=2#ray/upnp/ssdp">from这里。

I'm trying to implement a very simple SSDP functionality into my android app taken from here.

我的应用程序发送一个包含相关的M-SEARCH消息到广播地址没有任何问题的一些UDP数据包。问题是,我应该从正在运行的UPnP服务器等设备进行正确的响应返回。出于某种原因,我只接受完全一样的数据包后,我从我的Andr​​oid设备发送的。

My application sends some UDP packets containing a relevant M-SEARCH message to the broadcasting address without any issue. The problem is, I should be getting a proper response back from other devices that's running a UPNP server. For some reason, I'm only receiving the exact same packets back I sent from my android device.

MainActivity.java

MainActivity.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报文传输实际完成

SSDPSocket.java where the UDP packet transmission is actually done

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广播字符串 (也许无关,我遇到了,但为了以防万一的问题)

SSDPSearchMsg.java for constructing SSDP Broadcast string (Probably unrelated to the problem I'm experiencing but just in case)

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

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";
}

我也确信,清单包括相关权限:

I also made sure that the manifest includes relevant permissions:

 <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" />

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

I'm testing the app on an actual device, not on emulator.

任何援助将AP preciated。

Any assistance would be appreciated.

在注释编辑:

组播本身应该没有问题。我已经下载了所谓的BubbleUPNP测试SSDP功能的应用程序。果然,Wireshark的正确捕获从手机发送到广播地址SSDP协议中的所有信息:

Multicast itself should work without issue. I've downloaded an app called BubbleUPNP to test the SSDP functionality. Sure enough, wireshark properly captures all messages sent from the phone to the broadcasting address in 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

所以是的,这是毫无疑问的,一个执行问题。没有错,该设备。

So yeah, this is without a doubt, an implementation issue. Nothing wrong with the device.

推荐答案

奇怪。我固定的问题,但我真的不知道该怎么做它的工作。

Weird. I fixed the issue but I'm genuinely not sure what made it work.

下面有一些变化,我做了:

Here are some changes that I made:

而不是指定一个固定端口的,我做到了动态分配的可用端口。

Instead of assigning a fixed port, I made it dynamically allocate an available port.

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-搜索消息结构,包括它的顺序。

I also changed the M-Search message structure, including its order.

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

和一切突然作品。为什么它的工作原理是超越我。我的previous执行如下的SSDP协议,据我可以告诉。

And everything suddenly works. Why it works is beyond me. My previous implementation follows the SSDP protocol as far as I can tell.

这篇关于无法接收使用SSDP正确的UDP数据包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆