前面一篇博客里面已经介绍过SSDP协议原理,本篇博客将实现实现Android上的SSDP协议。

关键技术分析:1、发送广播;须要发送送广播,所以须要使用MulticastSocket、SocketAddress、InetAddress,须要掌握。

2、SSDP数据报格式;标准的SSDP Server解析的时候对于分段的字段选用的特征码是"\r\n",须要特别注意。

3、訪问权限;须要互联网,要在Mainfest中加入�联网的相关权限。

下面是我的源代码:

1、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;

public static final String SL_MSEARCH = "M-SEARCH * HTTP/1.1";

public static final String SL_OK = "HTTP/1.1 200 OK";

public static final String ST_Product = "ST:urn:schemas-upnp-org:device:Server:1";

public static final String Found = "ST=urn:schemas-upnp-org:device:";

public static final String Root = "ST:urn:schemas-upnp-org:device:DZBA_HomeDP:1";

}

2、SSDPSearchMsg .java

public class SSDPSearchMsg {

static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT;

static final String MAN = "Man:\"ssdp:discover\"";

static final String NEWLINE = "\r\n";

int mMX = 5; /* 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("MX:" + mMX).append(NEWLINE);

content.append(mST).append(NEWLINE);

content.append(NEWLINE);

return content.toString();

}

}

3、SSDPSocket .java

public class SSDPSocket {



SocketAddress mSSDPMulticastGroup;

MulticastSocket mSSDPSocket;

InetAddress broadcastAddress;



public SSDPSocket() throws IOException {

mSSDPSocket = new MulticastSocket(58000); // 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();

}

}

}

4、SSDP .java

public class SSDP {

/* 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;

public static final String ST = "ST";

public static final String LOCATION = "LOCATION";

public static final String NT = "NT";

public static final String NTS = "NTS";

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



@SuppressWarnings("resource")

public static String parseHeaderValue(String content, String headerName) {

Scanner s = new Scanner(content);

s.nextLine(); // Skip the start line

while (s.hasNextLine()) {

String line = s.nextLine();

int index = line.indexOf(':');

String header = line.substring(0, index);

if (headerName.equalsIgnoreCase(header.trim())) {

return line.substring(index + 1).trim();

}

}

return null;

}



public static String parseHeaderValue(DatagramPacket dp, String headerName) {

return parseHeaderValue(new String(dp.getData()), headerName);

}



@SuppressWarnings("resource")

public static String parseStartLine(String content) {

Scanner s = new Scanner(content);

return s.nextLine();

}



public static String parseStartLine(DatagramPacket dp) {

return parseStartLine(new String(dp.getData()));

}

}

5、MainActivity .java

public class MainActivity extends Activity implements OnClickListener {

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

SSDPSocket sock = null;

try {

sock = new SSDPSocket();

for (int i = 0; i < 2; i++) {

// sock.send(searchContentDirectory.toString());

// sock.send(searchAVTransport.toString());

sock.send(searchProduct.toString());

// String s = "M-SEARCH * HTTP/1.1 \n HOST= 239.255.255.250:1900 \n MAN= \"ssdp:discover\" \n MX: 3 \n ST= upnp:rootdevice";

// sock.send(s);

Log.i("-------------", "发送的数据为:\n" + 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()).trim();

String ip = new String(dp.getAddress().toString()).trim();

Log.i("------------", "接收到的数据为:\n" + c + "數據來源IP:" + ip);

}

} catch (IOException e) {

Log.e("M-SEARCH", e.getMessage());

}

}

}

界面xml非常easy,仅仅有一个button

Mainfest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.ssdp"

    android:versionCode="1"

    android:versionName="1.0" >





    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="18" />





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





    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.example.ssdp.MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />





                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>





</manifest>

使用须知:须要有Server端执行,http://download.csdn.net/detail/zhu530548851/7451201下载源代码,该源代码是js的。

将Server放于Linux系统文件夹下,进入test文件夹,运行node server.js就可以。

须要Linux安装有nodejs:sudo apt-get install nodejs

这样在执行Androidclient就能够从Log中看到来自于Server的信息了。

Android源代码在此:http://download.csdn.net/detail/zhu530548851/7451179

个人辛勤劳动成果,如有转载,请注明出处,谢谢!

SSDP协议的Android实现以及使用的更多相关文章

  1. MQTT协议实现Android中的消息收发

    前言 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输),基于发布/订阅范式的消息协议,是一种极其简单和轻量级的消息协议,专为受限设备和低带宽.高延迟 ...

  2. 基于XMPP协议的Android即时通信系

    以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务 ...

  3. Modbus工业协议在Android中的应用

    现在工业信息画发展,很多工厂都需要做信息化展示,通常都是利用Android一体机来进行展示和交互. Modbus协议是全球第一个用于工业现场的总线协议,与外设交互可以采用串口通信,tcp等方式:通常在 ...

  4. 采用MQTT协议实现android消息推送(4)选fusesource-mqtt-client为客户端

    1.简介 一个java写的mqtt客户端.项目地址: https://github.com/fusesource/mqtt-client 2.引入fusesource-mqtt-client库 Fil ...

  5. 采用MQTT协议实现android消息推送(2)MQTT服务端与客户端软件对比、android客户端示列表

    1.服务端软件对比 https://github.com/mqtt/mqtt.github.io/wiki/servers 名称(点名进官网) 特性 简介 收费 支持的客户端语言 IBM MQ 完整的 ...

  6. 采用MQTT协议实现android消息推送(1)MQTT 协议简介

    1.资料 mqtt官网 http://mqtt.org/ 服务端程序列表 https://github.com/mqtt/mqtt.github.io/wiki/servers 客户端库列表 http ...

  7. Android与服务器端数据交互(基于SOAP协议整合android+webservice)

    http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html 上一节中我们通过http协议,采用HttpClient向服务器端a ...

  8. 采用MQTT协议实现android消息推送(3)选ActiveMQ当服务端

    官网: http://activemq.apache.org/ 1.简介 强壮.快速.客户端支持多种语言的mqtt服务端软件. 2.特性 MQTT v3.1.AMQP v1.0.Stomp .Open ...

  9. android deep link(深度链接)与自定义协议!

    此自定义仅供参考! 首先打开androidManifest.xml 在MainActivity中添加如下内容: <activity android:name=".MainActivit ...

随机推荐

  1. Oracle EBS-SQL (INV-1):库存货位列表.sql

    select inventory_location_id, organization_id, description, subinventory_code, segment1 inventory_lo ...

  2. 接收时必须库存可处理标识为Y

    应用 Oracle Inventory 层 Level Function 函数名 Funcgtion Name RCV_RCVRCERC 表单名 Form Name RCVRCERC 说明 Descr ...

  3. VC中实现带有背景位图的树型控件

    当前许多应用程序都在使用树型控件时为其添加了背景位图,增强的控件的魅力,然而对于Visual C++编程爱好者来说,使用Visual C++MFC提供的树型控件(CTreeCtrl)本身就是一个难点, ...

  4. ThreadPool.QueueUserWorkItem的性能问题

    在WEB开发中,为了降低页面等待时间提高用户体验,我们往往会把一些浪费时间的操作放到新线程中在后台执行. 简单的实现代码就是: //代码一 new Thread(()=>{ //do somet ...

  5. 一步一步挖出Compute

    前几天在做结账的时候,对数据表DataGridView控件的单列求和纠结了一番.        如今差点儿养成了习惯,对于一些东西疏于開始的思考,不会先想到百度,这里我是先想到了第一版的机房收费那块的 ...

  6. CentOS配置ftp服务器

    1.首先更新yum 源 yum update 2. 安装vsftpd yum install vsftpd -y   // 安装    移除是 yum remove vsftpd 3. 配置Vsftp ...

  7. Asp.Net Memcached安装配置使用、安全性

    Memcached安装配置使用  一,准备        你需要有一下软件:       VS.NET(05/08)       SQLSERVER       memcached服务器端以及客户端类 ...

  8. 在View中使用CGridCtrl时出现系统异常

    一.简介 我的程序是单文档程序,我的View视图需要使用CGridCtrl,于是我把CGridCtrl作为子窗口嵌入到View中覆盖住整个View.由于不能像gridctrl_demo227那样直接在 ...

  9. 列求key出现的频率

    1 cat mc.log | grep LOGIN_GET | awk '{print $9}' | sort | uniq -c

  10. WPF中常用控件的属性

    Source = new BitmapImage( new Uri( WangCaiConfig.GetCurrentDirectory() + imgStr, UriKind.RelativeOrA ...