1. 程式人生 > >廣播與組播

廣播與組播

組播

將同一網路段的裝置進行邏輯上的分組。如設定一個組播地址,所有進入該地址的裝置是同一個組。任意一個裝置向該組傳送訊息即為組播。

廣播

將訊息傳送給區域網中的每一個裝置即為廣播。

組播與廣播最大的不同在於傳送訊息的地址不同。

程式碼示例:

傳送端

fun sendMultiBroadcast() {
        if (multicastLock?.isHeld!!) {
            var multicastSocket = MulticastSocket(8600)
            var address = InetAddress.getByName(IP_ADDRESS)
            if (!address.isMulticastAddress) {
                Log.d(TAG, "該地址不是組播地址")
            }
            multicastSocket.joinGroup(address)

            var datagramPacket: DatagramPacket?

            val buf = "hah  i  changed already".toByteArray()
            datagramPacket = DatagramPacket(buf, buf.size, address, 8600)       // 本地的socket埠為8600,所以該socket也可以接收來自自已的訊息

            while (true) {
                multicastSocket.send(datagramPacket)    // 在傳送時候如果切換網路,則報java.io.IOException: Network is unreachable錯誤,注意
                Thread.sleep(2000)
                Log.i(TAG, "傳送訊息到8600埠")
            }

            multicastSocket.leaveGroup(address)
            multicastSocket.close()
        }
    }

有的網路資料顯示,android預設不接收組播訊息,需要手動開啟。如下程式碼所示:

var wifiManager: WifiManager? = null
    var multicastLock: WifiManager.MulticastLock? = null

    /**
     * 獲取multicast鎖,網路資料表明android為了節約電量,預設不接收組播訊息。
     *
     * 但經過實際demo執行顯示,遮蔽該程式碼,一臺三星和一臺華為平板之間也是可以正常通訊的。
     */
    private fun openMulticastLock() {
        wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        multicastLock = wifiManager?.createMulticastLock("multicast.test")
        multicastLock?.acquire()
    }

接收端程式碼如下:

fun sendMultiBroadcast() {
        if (multicastLock?.isHeld!!) {
            var multicastSocket = MulticastSocket(8600)
            multicastSocket.timeToLive = 254
            var address = InetAddress.getByName(IP_ADDRESS)
            if (!address.isMulticastAddress) {
                Log.d(TAG, "該地址不是組播地址")
            }
            multicastSocket.joinGroup(address)
            Log.i(TAG, "加入組播")

            val rev = ByteArray(512)
            var revPacket = DatagramPacket(rev, rev.size)
            try {
                multicastSocket.receive(revPacket)
            } catch (e: Exception) {
                Log.e(TAG, "接收錯誤", e)
            }

            Log.i(TAG, "data is " + String(revPacket.data))
            mMainHandler.post {
                tv_msg.text = String(revPacket.data) + revPacket.address.hostAddress
            }

            multicastSocket.leaveGroup(address)
            multicastSocket.close()
        }
    }

    companion object {
        const val TAG = "sx"
        const val IP_ADDRESS = "239.0.0.1"
        const val SEND_ID = 0x0001
    }

其中,傳送端和接收端的ip地址和埠要一致。

兩臺裝置如果同在一個區域網內可以通過此種方法通訊。