Socket 通信
问题
在 Android 中 Socket 通信用于哪些场景?如何实现本地 Socket IPC?
答案
Socket vs Binder
| 特性 | Binder | Socket |
|---|---|---|
| 场景 | Android 进程间通信 | 通用网络通信 / 本地 IPC |
| 性能 | 1 次拷贝 | 2 次拷贝 |
| 安全 | 内核验证身份 | 需自行验证 |
| 跨网络 | ❌ | ✅ |
| Android 使用 | 系统 IPC 首选 | Zygote 通信、adb |
本地 Socket 通信
Android 中 Zygote 进程使用 LocalSocket(Unix Domain Socket)接收 AMS 的 fork 请求:
// Server 端
class LocalSocketServer {
fun start() {
val server = LocalServerSocket("my_socket")
thread {
while (true) {
val client = server.accept()
handleClient(client)
}
}
}
private fun handleClient(client: LocalSocket) {
val input = BufferedReader(InputStreamReader(client.inputStream))
val output = PrintWriter(client.outputStream, true)
val message = input.readLine()
output.println("Server received: $message")
client.close()
}
}
// Client 端
class LocalSocketClient {
fun send(message: String): String {
val socket = LocalSocket()
socket.connect(LocalSocketAddress("my_socket"))
val output = PrintWriter(socket.outputStream, true)
val input = BufferedReader(InputStreamReader(socket.inputStream))
output.println(message)
val response = input.readLine()
socket.close()
return response
}
}
Android 中的 Socket 使用场景
- Zygote 通信:AMS 通过 LocalSocket 通知 Zygote fork 新进程
- adb 调试:adb 通过 TCP Socket 与设备通信
- 应用内 WebSocket:IM、实时推送
- 跨设备通信:局域网设备发现、数据传输
推荐方案
Android 进程间通信优先使用 Binder(AIDL/Messenger/ContentProvider)。Socket 适合跨网络通信或与非 Android 平台(如 Native 进程、PC)交互的场景。
常见面试问题
Q1: Zygote 为什么使用 Socket 而不是 Binder?
答案:
Zygote 是所有应用进程的父进程,在 fork 子进程时需要保证单线程(fork 多线程进程会导致死锁等问题)。而 Binder 通信需要在进程中启动 Binder 线程池(多线程),与 fork 的安全要求冲突。Socket 是单线程通信模型,可以安全地在 fork 前后使用。