| | |
| | | import okio.ByteString |
| | | import org.json.JSONObject |
| | | import java.util.LinkedList |
| | | import java.util.concurrent.CopyOnWriteArrayList |
| | | import java.util.concurrent.TimeUnit |
| | | import java.util.concurrent.atomic.AtomicBoolean |
| | | |
| | | //WebSocket客户端 |
| | | class WebSocketClient( |
| | |
| | | ) { |
| | | private var webSocket: WebSocket? = null |
| | | private var okHttpClient: OkHttpClient? = null |
| | | private var isConnecting = false |
| | | private var isConnected = false |
| | | private var isConnecting = AtomicBoolean(false) |
| | | private var isConnected = AtomicBoolean(false) |
| | | |
| | | private var reconnectCount = 0 |
| | | private val gson = Gson() |
| | | private val ioCoroutineScope = CoroutineScope(Dispatchers.IO) |
| | | |
| | | // 监听器列表 |
| | | private val listeners = mutableListOf<IWebSocketListener>() |
| | | private val listeners = CopyOnWriteArrayList<IWebSocketListener>() |
| | | |
| | | // 心跳相关 |
| | | private var heartbeatJob: Job? = null |
| | |
| | | * 连接WebSocket |
| | | */ |
| | | fun connect(isFirstConnect: Boolean) { |
| | | if (isConnecting || isConnected) { |
| | | if (isConnecting.get() || isConnected.get()) { |
| | | LogUtils.d(TAG, "WebSocket正在连接或已连接") |
| | | return |
| | | } |
| | | |
| | | isConnecting = true |
| | | isConnecting.set(true) |
| | | reconnectCount = 0 |
| | | |
| | | ioCoroutineScope.launch { |
| | |
| | | |
| | | LogUtils.i(TAG, "开始连接WebSocket: ${config.WS_URL}") |
| | | } catch (e: Exception) { |
| | | isConnecting = false |
| | | isConnecting.set(false) |
| | | LogUtils.d(TAG, "连接WebSocket失败: ${e.message}") |
| | | notifyConnectFailed(e) |
| | | } |
| | |
| | | override fun onOpen(webSocket: WebSocket, response: Response) { |
| | | LogUtils.i(TAG, "WebSocket连接成功") |
| | | |
| | | isConnecting = false |
| | | isConnected = true |
| | | isConnecting.set(false) |
| | | isConnected.set(true) |
| | | reconnectCount = 0 |
| | | this@WebSocketClient.webSocket = webSocket |
| | | |
| | |
| | | |
| | | override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { |
| | | LogUtils.w(TAG, "WebSocket正在关闭: code=$code, reason=$reason") |
| | | isConnected = false |
| | | isConnected.set(false) |
| | | stopHeartbeat() |
| | | } |
| | | |
| | | override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { |
| | | LogUtils.w(TAG, "WebSocket已关闭: code=$code, reason=$reason") |
| | | isConnected = false |
| | | isConnected.set(false) |
| | | stopHeartbeat() |
| | | notifyDisconnected(code, reason) |
| | | |
| | |
| | | |
| | | override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { |
| | | LogUtils.d(TAG, "WebSocket连接失败: ${t.message}") |
| | | isConnecting = false |
| | | isConnected = false |
| | | isConnecting.set(false) |
| | | isConnected.set(false) |
| | | stopHeartbeat() |
| | | notifyConnectFailed(t) |
| | | |
| | |
| | | * 发送消息 |
| | | */ |
| | | fun sendMessage(message: String): Boolean { |
| | | return if (isConnected) { |
| | | return if (isConnected.get()) { |
| | | try { |
| | | webSocket?.send(message) |
| | | LogUtils.d(TAG, "发送消息成功: $message") |
| | |
| | | LogUtils.i(TAG, "主动断开WebSocket连接") |
| | | |
| | | stopHeartbeat() |
| | | isConnecting = false |
| | | isConnected = false |
| | | isConnecting.set(false) |
| | | isConnected.set(false) |
| | | reconnectCount = config.MAX_RECONNECT_COUNT // 阻止重连 |
| | | |
| | | webSocket?.close(code, reason) |
| | |
| | | * 重新连接 |
| | | */ |
| | | fun reconnect() { |
| | | if (isConnecting) { |
| | | if (isConnecting.get()) { |
| | | LogUtils.d(TAG, "已经在重连中...") |
| | | return |
| | | } |
| | |
| | | */ |
| | | fun getConnectionState(): ConnectionState { |
| | | return when { |
| | | isConnected -> ConnectionState.CONNECTED |
| | | isConnecting -> ConnectionState.CONNECTING |
| | | isConnected.get() -> ConnectionState.CONNECTED |
| | | isConnecting.get() -> ConnectionState.CONNECTING |
| | | else -> ConnectionState.DISCONNECTED |
| | | } |
| | | } |
| | |
| | | stopHeartbeat() |
| | | |
| | | heartbeatJob = ioCoroutineScope.launch { |
| | | while (isActive && isConnected) { |
| | | while (isActive && isConnected.get()) { |
| | | delay(config.PING_INTERVAL * 1000) |
| | | if (isConnected) { |
| | | if (isConnected.get()) { |
| | | setAuthMessage() |
| | | setHeartbeatMessage() |
| | | setPositionMessage() |
| | |
| | | |
| | | ioCoroutineScope.launch { |
| | | delay(delay * 1000) |
| | | if (!isConnected && !isConnecting) { |
| | | if (!isConnected.get() && !isConnecting.get()) { |
| | | connect(false) |
| | | } |
| | | } |