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 ...
随机推荐
- linux下flashplayer更新_最新版传送
http://get.adobe.com/cn/flashplayer/ 官网地址,全部最新的flash都在这了,左边选择你要下载的类型,右边点击下载就行了. 最简单的方法就是 下载rpm包,命令rp ...
- 标准C编程-笔记全集
C语言的基本概念 编写一个简单的C程序,后缀名保存为c(本次文件名为a.c) gcc:对c程序进行编译和连接:gcc a.c ./a.out:运行程序,输出程序的结果:其中a是c程序的文件名 说明:其 ...
- 添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)
添加EF上下文对象,添加接口.实现类以及无处不在的依赖注入(DI) 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建 ...
- kvm在线磁盘扩展
1,查看指定kvm虚拟机的现有磁盘domblklist
- CodeForces - 61E Enemy is weak
Description The Romans have attacked again. This time they are much more than the Persians but Shapu ...
- wxWidgets刚開始学习的人导引(2)——下载、安装wxWidgets
wxWidgets刚開始学习的人导引全目录 PDF版及附件下载 1 前言2 下载.安装wxWidgets3 wxWidgets应用程序初体验4 wxWidgets学习资料及利用方法指导5 用wxS ...
- pushViewController自定义动画
实现的主要代码如下: CATransition *transition = [CATransition animation]; transition.duration = 1.0f; transiti ...
- 怎样在UICollectionView中添加Header和footer
---恢复内容开始--- 怎样在UICollectionView中添加Header和footer 转载于http://my.oschina.net/zboy/blog/221525 摘要 来自-htt ...
- SQL serve创建与调用存储过程
(1)创建 2编写存储过程(创建传参的存储过程)存储过程语法网络上很多不在累述 语法解析 Use Person 指定在那个数据库下建立存储过程 if (object_id('MyFunction', ...
- 电脑技巧---完全控制面板---上帝模式(God Mode)
简介 上帝模式,即"God Mode”,或称为“完全控制面板”.是Windows 系统中隐藏的一个简单的文件夹窗口,但包含了几乎所有Windows系统的设置,如控制面板的功能.界面个性化.辅 ...