网络唤醒应用仅适用于最近关闭的设备
Wake-on-Lan app only works for recently shutdown devices
我用 Kotlin 编写了一个小应用程序,它通过本地网络向智能电视发送一个 Magic Packet。我使用 this approach (code),用 Kotlin 重写(另外我硬编码了 IP 和 MAC 用于测试目的)。
当电视关闭时,我可以使用我的应用程序轻松重启它。一段时间后,它不再起作用了。
代码
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
fun main() {
magicPacket("A8:23-FE:A0:5C:DB", "192.168.xx.xxx", 7)
}
/**
* Android:
* Network interaction starting in new Thread!
*/
fun magicPacket(mac: String, ip: String, PORT: Int = 7) {
// throws IllegalThreadStateException without declaration
//val t = thread {
val packet = buildPacket(mac)
val datagramSocket = DatagramSocket()
try {
datagramSocket.send(
DatagramPacket(
packet,
packet.size,
InetAddress.getByName(ip),
PORT
)
)
datagramSocket.close()
} catch (e: Exception) {
e.printStackTrace()
}
//}
}
private fun buildPacket(mac: String): ByteArray {
// prepare packet (6 bytes header) (16 * 6 bytes MAC)
val temp = ByteArray(6 + 6 * 16)
val macBytes = ByteArray(6)
for (i in 0..5) {
temp[i] = 0xFF.toByte()
macBytes[i] = mac.split(":", "-")[i].toInt(16).toByte()
}
for (i in 6 until temp.size step macBytes.size) System.arraycopy(
macBytes,
0,
temp,
i,
macBytes.size
)
return temp
}
我在代码中尝试了什么
- 我更改了端口号(从 运行dom(11111、55555、快速 google 搜索建议的端口 0、7、9 开始)都失败了
- 发送的不是一个而是 10 到 100 个数据包
- i 运行 该应用程序作为来自 Intellij 的 java (kotlin) 项目也在我的电脑上,结果相同
我发现了什么
- WOL 并非在所有设备上都有效
- 电源状态可能很重要
- Wake On Lan无论如何都能唤醒设备,所以我认为问题出在应用程序上,而不是任何设置
- 所有网络 IP 和 MAC 都是静态的
发送wakeonlan数据包时,需要确保目标设备能够接收到数据包。
目前,您正在将数据包发送到设备的 IPv4 地址。
当您的计算机必须向 IPv4 地址发送数据包时,它需要知道其 MAC 地址。所以它询问网络“谁有 IPv4 192.168.2.32?告诉我你的 mac 地址”。由于您的电视已关机,因此它没有响应。
真正的 LAN 唤醒数据包永远不会发送,因为它不知道目标 mac 地址。
那么真正的问题就变成了,为什么关机后直接就可以了,这是因为你的OS有一个IPv4+mac地址的列表table,所以它可以快速发送数据包。您可以在 Windows
上使用命令 arp -av
查看此列表
请注意,当您的程序成功唤醒电视时显示“动态”,但未能唤醒电视时显示“无效”。
一个解决方案是将数据包发送到每个设备接收的广播 IPv4 地址。此 IPv4 地址通常以 .255
结尾,具有典型的消费者 IPv4 范围。
我用 Kotlin 编写了一个小应用程序,它通过本地网络向智能电视发送一个 Magic Packet。我使用 this approach (code),用 Kotlin 重写(另外我硬编码了 IP 和 MAC 用于测试目的)。
当电视关闭时,我可以使用我的应用程序轻松重启它。一段时间后,它不再起作用了。
代码
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
fun main() {
magicPacket("A8:23-FE:A0:5C:DB", "192.168.xx.xxx", 7)
}
/**
* Android:
* Network interaction starting in new Thread!
*/
fun magicPacket(mac: String, ip: String, PORT: Int = 7) {
// throws IllegalThreadStateException without declaration
//val t = thread {
val packet = buildPacket(mac)
val datagramSocket = DatagramSocket()
try {
datagramSocket.send(
DatagramPacket(
packet,
packet.size,
InetAddress.getByName(ip),
PORT
)
)
datagramSocket.close()
} catch (e: Exception) {
e.printStackTrace()
}
//}
}
private fun buildPacket(mac: String): ByteArray {
// prepare packet (6 bytes header) (16 * 6 bytes MAC)
val temp = ByteArray(6 + 6 * 16)
val macBytes = ByteArray(6)
for (i in 0..5) {
temp[i] = 0xFF.toByte()
macBytes[i] = mac.split(":", "-")[i].toInt(16).toByte()
}
for (i in 6 until temp.size step macBytes.size) System.arraycopy(
macBytes,
0,
temp,
i,
macBytes.size
)
return temp
}
我在代码中尝试了什么
- 我更改了端口号(从 运行dom(11111、55555、快速 google 搜索建议的端口 0、7、9 开始)都失败了
- 发送的不是一个而是 10 到 100 个数据包
- i 运行 该应用程序作为来自 Intellij 的 java (kotlin) 项目也在我的电脑上,结果相同
我发现了什么
- WOL 并非在所有设备上都有效
- 电源状态可能很重要
- Wake On Lan无论如何都能唤醒设备,所以我认为问题出在应用程序上,而不是任何设置
- 所有网络 IP 和 MAC 都是静态的
发送wakeonlan数据包时,需要确保目标设备能够接收到数据包。
目前,您正在将数据包发送到设备的 IPv4 地址。
当您的计算机必须向 IPv4 地址发送数据包时,它需要知道其 MAC 地址。所以它询问网络“谁有 IPv4 192.168.2.32?告诉我你的 mac 地址”。由于您的电视已关机,因此它没有响应。
真正的 LAN 唤醒数据包永远不会发送,因为它不知道目标 mac 地址。
那么真正的问题就变成了,为什么关机后直接就可以了,这是因为你的OS有一个IPv4+mac地址的列表table,所以它可以快速发送数据包。您可以在 Windows
上使用命令arp -av
查看此列表
请注意,当您的程序成功唤醒电视时显示“动态”,但未能唤醒电视时显示“无效”。
一个解决方案是将数据包发送到每个设备接收的广播 IPv4 地址。此 IPv4 地址通常以 .255
结尾,具有典型的消费者 IPv4 范围。