• SSDP协议的Android实现以及使用


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

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

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

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

    下面是我的源代码:

    1、SSDPConstants.java

    public class SSDPConstants {
    /* New line definition */
    public static final String NEWLINE = " ";
    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 = " ";
    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 = " ";
    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 HOST= 239.255.255.250:1900 MAN= "ssdp:discover" MX: 3 ST= upnp:rootdevice";
    // sock.send(s);
    Log.i("-------------", "发送的数据为: " + 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("------------", "接收到的数据为: " + 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



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

  • 相关阅读:
    简单数学问题
    MFC 注册表编程
    Windows多线程端口扫描
    MFC Socket双向通信
    凯撒加密
    单片机滤波
    大数素性检验
    大数加法乘法
    Unsafe Code
    委托
  • 原文地址:https://www.cnblogs.com/yxwkf/p/3942214.html
Copyright © 2020-2023  润新知