SSDP协议的Android实现以及使用
前面一篇博客里面已经介绍过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实现以及使用的更多相关文章
- MQTT协议实现Android中的消息收发
前言 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输),基于发布/订阅范式的消息协议,是一种极其简单和轻量级的消息协议,专为受限设备和低带宽.高延迟 ...
- 基于XMPP协议的Android即时通信系
以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务 ...
- Modbus工业协议在Android中的应用
现在工业信息画发展,很多工厂都需要做信息化展示,通常都是利用Android一体机来进行展示和交互. Modbus协议是全球第一个用于工业现场的总线协议,与外设交互可以采用串口通信,tcp等方式:通常在 ...
- 采用MQTT协议实现android消息推送(4)选fusesource-mqtt-client为客户端
1.简介 一个java写的mqtt客户端.项目地址: https://github.com/fusesource/mqtt-client 2.引入fusesource-mqtt-client库 Fil ...
- 采用MQTT协议实现android消息推送(2)MQTT服务端与客户端软件对比、android客户端示列表
1.服务端软件对比 https://github.com/mqtt/mqtt.github.io/wiki/servers 名称(点名进官网) 特性 简介 收费 支持的客户端语言 IBM MQ 完整的 ...
- 采用MQTT协议实现android消息推送(1)MQTT 协议简介
1.资料 mqtt官网 http://mqtt.org/ 服务端程序列表 https://github.com/mqtt/mqtt.github.io/wiki/servers 客户端库列表 http ...
- Android与服务器端数据交互(基于SOAP协议整合android+webservice)
http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html 上一节中我们通过http协议,采用HttpClient向服务器端a ...
- 采用MQTT协议实现android消息推送(3)选ActiveMQ当服务端
官网: http://activemq.apache.org/ 1.简介 强壮.快速.客户端支持多种语言的mqtt服务端软件. 2.特性 MQTT v3.1.AMQP v1.0.Stomp .Open ...
- android deep link(深度链接)与自定义协议!
此自定义仅供参考! 首先打开androidManifest.xml 在MainActivity中添加如下内容: <activity android:name=".MainActivit ...
随机推荐
- Thinkphp的时间判断
在做项目的过程中,非常频繁地遇到时间这个问题,像时间的比较,特定时间执行某一操作,但是现在只解决了一部分问题,先说明一下时间的判断问题. 很简单,时间,不断使date(),now(),都是字符串类型的 ...
- SQL文件导入到mysql乱码
在输入中文之前先SET NAMES GBK 彻底解决MYSQL中文乱码的办法((5.5以后版本:) 修改MYSQL配置文件my.ini [client] default-character-set=u ...
- MongoDB(二)
通过程序来操作数据库: //链接字符串 string connectionString = "mongodb://192.168.1.107"; //数据库名 string dat ...
- Linux下安装QT和OpenGL后QT无法使用OpenGL的解决方法
我的系统为Ubuntu14.04,用apt-get安装了实现了OpenGl的mesa,QT则是用官网下载的run文件来安装的. 好了,现在两个都分别有了,所以要在qt下尝试写OpenGl代码. 之前试 ...
- 蓝牙1.1、蓝牙1.2、蓝牙2.0(蓝牙2.0+EDR)区别
蓝牙1.2版本相对于1.1版本: 1.Adaptive Frequency Hopping(AFH):即所谓适应性跳频技术,主要的功能是用来减少蓝牙产品与其它无线通讯装置之间所产生的干扰问题 2.Ex ...
- delphi 基础书籍推荐
本文所推荐的书,我均仔细读过,受益良多. 1. Pascal 精要.下载Pascal精要 本书讲Pascal 语言基本知识. 2. Object Pascal 参考(中英文对照版).下载Object ...
- Silverlight下的Socket通讯
http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html 在Silverlight中进行通讯,只能使用4502-453 ...
- Solr学习(2) Solr4.2.0+IK Analyzer 2012
Solr学习(二) Solr4.2.0+IK Analyzer 2012 开场白: 本章简单讲述如何在solr中配置著名的 IK Analyzer 分词器. 本章建立在 Solr学习(一) 基础上进 ...
- 如何阅读mysql源码
在微博上问mysql高手,如何阅读mysql 源码大致给了下面的一些建议: step 1,知道代码的组织结构(官方文档http://t.cn/z8LoLgh: Step2: 尝试大致了解一条sql涉及 ...
- 比较两个data日期之间的天数相差
先将字符串转化为Date类型 转化方式参看:http://blog.csdn.net/caoyinghui1986/archive/2008/04/18/2303570.aspx 然后在调用Date. ...