解决网络状态变化的问题
This commit is contained in:
parent
779947677c
commit
e68bf7e106
@ -86,7 +86,7 @@ actor SDLContextActor {
|
||||
nonisolated private let arpServer: ArpServer
|
||||
|
||||
// 网络状态变化的健康
|
||||
private var monitor: SDLNetworkMonitor?
|
||||
private var monitor: SDLPathMonitor?
|
||||
private var monitorWorker: Task<Void, Never>?
|
||||
|
||||
// 内部socket通讯
|
||||
@ -338,20 +338,25 @@ actor SDLContextActor {
|
||||
self.monitorWorker = nil
|
||||
|
||||
// 启动monitor
|
||||
let monitor = SDLNetworkMonitor()
|
||||
let monitor = SDLPathMonitor()
|
||||
monitor.start()
|
||||
SDLLogger.log("[SDLContext] monitor started")
|
||||
self.monitor = monitor
|
||||
|
||||
self.monitorWorker = Task.detached {
|
||||
for await event in monitor.eventStream {
|
||||
switch event {
|
||||
case .changed:
|
||||
// 需要重新探测网络的nat类型
|
||||
await self.probeNatType()
|
||||
SDLLogger.log("didNetworkPathChanged, nat type is:")
|
||||
case .unreachable:
|
||||
SDLLogger.log("didNetworkPathUnreachable")
|
||||
self.monitorWorker = Task {
|
||||
for await status in monitor.statusStream() {
|
||||
switch status {
|
||||
case .satisfied:
|
||||
SDLLogger.log("[Path] stable satisfied", for: .debug)
|
||||
// await contextActor.networkPathDidBecomeSatisfied(snapshot)
|
||||
case .unsatisfied:
|
||||
SDLLogger.log("[Path] stable unsatisfied", for: .debug)
|
||||
// await contextActor.networkPathDidBecomeUnsatisfied(snapshot)
|
||||
case .requiresConnection:
|
||||
SDLLogger.log("[Path] stable requiresConnection", for: .debug)
|
||||
|
||||
@unknown default:
|
||||
SDLLogger.log("[Path] stable unknown", for: .debug)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
Tun/Punchnet/NWPath/SDLPathDebounceActor.swift
Normal file
54
Tun/Punchnet/NWPath/SDLPathDebounceActor.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// SDLPathDebounceActor.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/4/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
actor SDLPathDebounceActor {
|
||||
private var lastSnapshot: SDLPathSnapshot?
|
||||
private var debounceTask: Task<Void, Never>?
|
||||
|
||||
private let delay: Duration
|
||||
|
||||
public let statusStream: AsyncStream<NWPath.Status>
|
||||
private let statusCont: AsyncStream<NWPath.Status>.Continuation
|
||||
|
||||
init(delay: Duration = .seconds(2)) {
|
||||
self.delay = delay
|
||||
let (stream, cont) = AsyncStream.makeStream(of: NWPath.Status.self)
|
||||
self.statusStream = stream
|
||||
self.statusCont = cont
|
||||
}
|
||||
|
||||
func submit(_ snapshot: SDLPathSnapshot) {
|
||||
guard snapshot != lastSnapshot else {
|
||||
return
|
||||
}
|
||||
|
||||
self.lastSnapshot = snapshot
|
||||
|
||||
self.debounceTask?.cancel()
|
||||
self.debounceTask = Task { [delay] in
|
||||
try? await Task.sleep(for: delay)
|
||||
|
||||
guard !Task.isCancelled else {
|
||||
return
|
||||
}
|
||||
await self.handleStableSnapshot(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleStableSnapshot(_ snapshot: SDLPathSnapshot) async {
|
||||
self.statusCont.yield(snapshot.status)
|
||||
}
|
||||
|
||||
func stop() {
|
||||
debounceTask?.cancel()
|
||||
debounceTask = nil
|
||||
}
|
||||
|
||||
}
|
||||
38
Tun/Punchnet/NWPath/SDLPathMonitor.swift
Normal file
38
Tun/Punchnet/NWPath/SDLPathMonitor.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// SDLPathMonitor.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/4/29.
|
||||
//
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
final class SDLPathMonitor {
|
||||
private let monitor = NWPathMonitor()
|
||||
private let queue = DispatchQueue(label: "com.sdlan.path-monitor")
|
||||
private let debouncer = SDLPathDebounceActor(delay: .seconds(2))
|
||||
|
||||
func start() {
|
||||
monitor.pathUpdateHandler = { path in
|
||||
let snapshot = SDLPathSnapshot(path)
|
||||
|
||||
Task {
|
||||
await self.debouncer.submit(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
monitor.start(queue: queue)
|
||||
}
|
||||
|
||||
func statusStream() -> AsyncStream<NWPath.Status> {
|
||||
return self.debouncer.statusStream
|
||||
}
|
||||
|
||||
func stop() {
|
||||
Task {
|
||||
await debouncer.stop()
|
||||
}
|
||||
monitor.cancel()
|
||||
}
|
||||
|
||||
}
|
||||
32
Tun/Punchnet/NWPath/SDLPathSnapshot.swift
Normal file
32
Tun/Punchnet/NWPath/SDLPathSnapshot.swift
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// PathSnapshot.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/4/29.
|
||||
//
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
struct SDLPathSnapshot: Equatable, Sendable {
|
||||
let status: NWPath.Status
|
||||
let isExpensive: Bool
|
||||
let isConstrained: Bool
|
||||
let supportsIPv4: Bool
|
||||
let supportsIPv6: Bool
|
||||
let supportsDNS: Bool
|
||||
let usesWiFi: Bool
|
||||
let usesWired: Bool
|
||||
let usesCellular: Bool
|
||||
|
||||
init(_ path: NWPath) {
|
||||
self.status = path.status
|
||||
self.isExpensive = path.isExpensive
|
||||
self.isConstrained = path.isConstrained
|
||||
self.supportsIPv4 = path.supportsIPv4
|
||||
self.supportsIPv6 = path.supportsIPv6
|
||||
self.supportsDNS = path.supportsDNS
|
||||
self.usesWiFi = path.usesInterfaceType(.wifi)
|
||||
self.usesWired = path.usesInterfaceType(.wiredEthernet)
|
||||
self.usesCellular = path.usesInterfaceType(.cellular)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user