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

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

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

@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 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 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

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:

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

Any assistance would be appreciated.

Edit upon comment:

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

And the response

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

}

...

}

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

}

}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值