package cn.trans88.taxiappkotlin.ledok import android.content.Context import android.util.Log import cn.trans88.taxiappkotlin.R import cn.trans88.taxiappkotlin.TaxiApp import cn.trans88.taxiappkotlin.logic.network.ConnManger import com.google.gson.GsonBuilder import com.trs88.kurolibrary.log.KuroLog import java.io.BufferedReader import java.io.DataOutputStream import java.io.File import java.io.FileOutputStream import java.io.FileReader import java.io.IOException import java.io.InputStream import java.net.ServerSocket import java.net.Socket import java.util.Timer import java.util.TimerTask import java.util.concurrent.TimeUnit class TaskSocketServer(private val context: Context, port: Int) { companion object { val TAG: String = TaskSocketServer::class.java.simpleName } var timer: Timer? = null private var file: File? = null private var fos: FileOutputStream? = null private var dos: DataOutputStream? = null private var startFlag = 0 private var endFlag = 0 //private byte[] globleBuff = new byte[1020]; var m_iCurFileSize: Int = 0 //当前文件的大小 var m_iCurFileRecvLength: Int = 0 //当前文件接收到的字节 private val bFileOpr = false var jsonBuff: ByteBuffer = ByteBuffer() private var soc: ServerSocket? = null private var client: Socket? = null private val dir: String? = null private var downloadDir: File? = null private val prot = 3333 private var recreate = true fun destroy() { Log.i(TAG, "destroy killLive。。。。") killLive() clear() if (client != null) { try { client!!.close() } catch (e: IOException) { e.printStackTrace() } client = null } try { if (soc != null) soc!!.close() soc = null } catch (e: IOException) { e.printStackTrace() } } fun listen() { Log.i(TAG, "listen") keepLive() while (soc != null && !soc!!.isClosed) { try { //只保持一个链接,新的进来就把老的断开 val socket = soc!!.accept() socket.soTimeout = 5000 if (client != null) { client!!.close() } client = socket Log.i(TAG, "new client is connected") clear() //edit by ljh@2024/4/28 优化ledOk发节目旧连接没断开,新连接发送不了数据问题 ThreadProcessor.getInstance().addThread { recvDataFromClient() } } catch (e: Exception) { Log.d(TAG, "Exception msg: " + e.message) e.printStackTrace() } } Log.i(TAG, "server 断开重建。。。。") } private fun keepLive() { if (timer == null) { timer = Timer() timer!!.schedule(object : TimerTask() { override fun run() { if (soc != null && !soc!!.isClosed) { Log.i(TAG, "server live 。。。。") recreate = false } else { Log.i(TAG, "server death 。。。。") recreate = true } } }, 5000, (30 * 1000).toLong()) } } private fun killLive() { Log.i(TAG, "killLive。。。。") if (timer != null) { timer!!.cancel() timer = null } } fun sendDataToClient(msg: String) { try { val bs = msg.toByteArray() if (client != null) { client!!.getOutputStream().write(bs) } } catch (e: Exception) { e.printStackTrace() } } fun recvDataFromClient() { var len = -1 val buff = ByteArray(4096) var input: InputStream? = null try { input = client!!.getInputStream() while ((input.read(buff).also { len = it }) != -1 ) { processData(buff, len) } } catch (e: Exception) { e.printStackTrace() Log.i(TAG, "出错重置。。。。") clear(); try { client?.close(); } catch (e: IOException) { e.printStackTrace(); } } finally { clear() if (input != null) { try { input.close() } catch (e: IOException) { throw RuntimeException(e) } } if (client != null) { try { client!!.close() } catch (e: IOException) { throw RuntimeException(e) } } } } fun clear() { if (file != null) { file!!.delete() file = null } if (fos != null) { try { fos!!.close() fos = null } catch (e: IOException) { e.printStackTrace() } } if (dos != null) { try { dos!!.close() dos = null } catch (e: IOException) { e.printStackTrace() } } startFlag = 0 endFlag = 0 m_iCurFileSize = 0 m_iCurFileRecvLength = 0 jsonBuff.clear() } private fun processData(buff: ByteArray, len: Int) { var i = 0 while (i < len) { if (file != null) { //文件已经打开,说明已经收到了fileStart,下面的数据准备写入文件 val iRestLength = len - i // m_iCurFileSize表示 ledOk发过来文件的大小,m_iCurFileRecvLength表示 当前文件接收到的字,累加起来 val iRestFileLength = m_iCurFileSize - m_iCurFileRecvLength // Log.d( // TAG, // "m_iCurFileSize:$m_iCurFileSize\nm_iCurFileRecvLength:$m_iCurFileRecvLength\niRestFileLength:$iRestFileLength" // ) // Log.d(TAG, "processData: file: ") //buff中剩余的字节数 大于 剩余未写入文件的字节数 if (iRestLength >= iRestFileLength) { //并且剩余文件未写入字节数 大于 0 if (iRestFileLength > 0) { //直接将iRestFileLength长度字节数写入文件,buff索引向后移动iRestFileLength个字节 try { val restBuff = ByteArray(iRestFileLength) System.arraycopy(buff, i, restBuff, 0, iRestFileLength) //// Log.i(TAG,"BS:"+Arrays.toString(restBuff)); if (fos == null) { fos = FileOutputStream(file) if (dos == null) { dos = DataOutputStream(fos) } //Log.i(TAG,"BS:"+Arrays.toString(restBuff)); KuroLog.i("TAG:processData:0") dos!!.write(restBuff) } else { if (dos == null) { dos = DataOutputStream(fos) } //Log.i(TAG,"BS:"+Arrays.toString(restBuff));\ KuroLog.i("TAG:processData:1") dos!!.write(restBuff) } m_iCurFileRecvLength += iRestFileLength i += iRestFileLength //文件写完了,关闭当前文件 startFlag = 0 } catch (e: Exception) { //Log.i(tag, "10000000000000000000"); e.printStackTrace() } } else { //Log.i(tag, "iRestFileLength <= 0"); if (iRestFileLength < 0) { Log.i(TAG, "iRestFileLength < 0") } } } else { try { val restBuff = ByteArray(iRestLength) //// Log.i(TAG,"BS:"+Arrays.toString(restBuff)); System.arraycopy(buff, i, restBuff, 0, iRestLength) //Log.i(tag, "00"); if (file != null) { //Log.i(tag, "01"); if (fos == null) { fos = FileOutputStream(file) if (dos == null) { dos = DataOutputStream(fos) } KuroLog.i("TAG:processData:2") dos!!.write(restBuff) } else { if (dos == null) { dos = DataOutputStream(fos) } // KuroLog.i("TAG:processData:3"); dos!!.write(restBuff) } } m_iCurFileRecvLength += iRestLength } catch (e: Exception) { //Log.i(tag, "1111111111111111111111111"); e.printStackTrace() } return } } // if (startFlag == 0) { if (buff[i] == '{'.toByte()) { startFlag = 1 jsonBuff.append(buff[i]) } } else if (startFlag == 1) { if (buff[i] == '"'.toByte()) { startFlag = 2 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 2) { if (buff[i] == '_'.toByte()) { startFlag = 3 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 3) { if (buff[i] == 't'.toByte()) { startFlag = 4 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 4) { if (buff[i] == 'y'.toByte()) { startFlag = 5 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 5) { if (buff[i] == 'p'.toByte()) { startFlag = 6 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 6) { if (buff[i] == 'e'.toByte()) { startFlag = 7 jsonBuff.append(buff[i]) } else { startFlag = 0 jsonBuff.clear() } } else if (startFlag == 7) { if (endFlag == 0) { if (buff[i] == 'x'.toByte()) { endFlag = 1 } } else if (endFlag == 1) { endFlag = if (buff[i] == 'i'.toByte()) { 2 } else { 0 } } else if (endFlag == 2) { endFlag = if (buff[i] == 'x'.toByte()) { 3 } else { 0 } } else if (endFlag == 3) { endFlag = if (buff[i] == 'u'.toByte()) { 4 } else { 0 } } else if (endFlag == 4) { endFlag = if (buff[i] == 'n'.toByte()) { 5 } else { 0 } } else if (endFlag == 5) { endFlag = if (buff[i] == '1'.toByte()) { 6 //jsonObject结束 } else { 0 } } else if (endFlag == 6) { endFlag = if (buff[i] == '"'.toByte()) { 7 //jsonObject结束 } else { 0 } } else if (endFlag == 7) { endFlag = if (buff[i] == '}'.toByte()) { 8 //jsonObject结束 } else { 0 } } jsonBuff.append(buff[i]) if (endFlag == 8) { val json = String(jsonBuff.buff, 0, jsonBuff.len()) processPackage(json) endFlag = 0 startFlag = endFlag jsonBuff.clear() } } i++ } } fun processPackage(json: String?) { if (json != null) { try { val gson = GsonBuilder().serializeNulls().create() val cmd = gson.fromJson(json, JsonCommand::class.java) if (cmd._type == "consult") { Log.d(TAG, "processPackage([json]): consult: $json") idList1 = cmd.idList ackList(cmd.idList) } else if (cmd._type == "proStart") { Log.d(TAG, "processPackage([json]): proStart: $json") } else if (cmd._type == "proEnd") { Log.d(TAG, "processPackage([json]): proEnd: $json") val ack = "{\"_type\":\"AckSuccess\"}" sendDataToClient(ack) client?.close() Log.d(TAG, "processPackage([json]): ack: $ack") //文件接收完成,可以开始播放 LedOkCommands.startLedOkActivity() } else if (cmd._type == "fileStart") { Log.d(TAG, "processPackage([json]): fileStart: $json") m_iCurFileSize = cmd.size m_iCurFileRecvLength = 0 if (!cmd.id!!.isEmpty() && file == null) { if (!downloadDir?.exists()!!) { downloadDir?.mkdirs(); } var path = "${downloadDir?.absolutePath}/${cmd.id}" file = File(path); if (!file!!.exists()) { Log.i(TAG, "create file :" + path); file!!.createNewFile(); } file!!.setWritable(true, true); } else if (!cmd.id!!.isEmpty() && file != null) { if (!file!!.canWrite()) { file!!.setWritable(true, true) } } } else if (cmd._type == "fileEnd") { Log.d(TAG, "processPackage([json]): fileEnd: $json") if (dos != null) { dos!!.flush() //将数据同步到达物理存储设备 val fd = fos!!.fd fd.sync() dos!!.close() } if (fos != null) fos!!.close() file!!.setWritable(false, true); fos = null dos = null file = null //TaskProcessor.getInstance(context).updateSourceFile(new SourceFile(cmd.id, servant.getCanUsedPath(context), FileState.Is_Downloaded)); } // else if (cmd._type == "BindAccount") { // Log.d(TAG, "processPackage: BindAccount") // val server = cmd.server!! // val tlsServer = cmd.tlsServer!! // val accountIdToken = cmd.accountIdToken!! // val bindModel = BindModel("", accountIdToken, server, tlsServer)!! // if (bindModel?.server != null && bindModel?.server != "") { // bindModel?.server = bindModel?.server + "/" // } // if (bindModel?.server != null && bindModel.server != "") { // bindModel.tlsServer = bindModel.tlsServer + "/" // } // val mbindAccount = ConnManger.mbindAccount(bindModel) // if (mbindAccount == true) { // val ack = "{\"_type\":\"AckSuccess\"}" // sendDataToClient(ack) // } else { // val ack = "{\"_type\":\"AckFailed\"}" // sendDataToClient(ack) // } // client?.close() // } } catch (e: Exception) { Log.i(TAG, "error:" + e.message) e.printStackTrace() } } } fun ackList(list: List?) { if (list.isNullOrEmpty()) { Log.i(TAG, "consult is empty") return } val downloadList: MutableList = ArrayList() for (id in list) { val file = File("${downloadDir?.absolutePath}/${id}") if (id == "program" || !file.exists()) { downloadList.add(id) } } var sl = "" for (i in downloadList.indices) { sl = if (i == 0) { sl + "\"" + downloadList[i] + "\"" } else { sl + ",\"" + downloadList[i] + "\"" } } val ack = "{\"_type\":\"consult\",\"idList\":[$sl]}" Log.d(TAG, "processPackage([json]): ack: $ack") sendDataToClient(ack) //发送出去 } inner class ByteBuffer { var buff: ByteArray private val unit = 3000 private var size: Int private var index: Int init { buff = ByteArray(unit) size = unit index = 0 } fun append(b: Byte) { if (index >= size) { Log.i(TAG, "================ index of ByteBuffer > size===============") size = size + unit val temp = ByteArray(size) System.arraycopy(buff, 0, temp, 0, index) buff = temp } buff[index] = b index++ } fun clear() { buff = ByteArray(unit) size = unit index = 0 } fun len(): Int { return index } } inner class JsonCommand { var _type: String? = null var proName: String? = null var proSize: Int = 0 var zVer: String? = null var id: String? = null var relative_path: String? = null var size: Int = 0 var data: String? = null var _id: String? = null var idList: List? = null var task: Task? = null // var bindModel: cn.trans88.taxiappkotlin.ledok.BindModel? = null var accountIdToken: String? = null var server: String? = null var tlsServer: String? = null } var idList1: List? = null init { downloadDir = File(TaxiApp.instance().filesDir, TaxiApp.instance().getString(R.string.dir_program)) Log.d(TAG, "downloadDir: $downloadDir") while (recreate) { try { // if (soc == null) { // destroy() soc = ServerSocket(port) recreate = false // } Log.i(TAG, "create...... ") } catch (e: Exception) { Log.i(TAG, e.message + "...............") try { TimeUnit.SECONDS.sleep(1) } catch (interruptedException: InterruptedException) { interruptedException.printStackTrace() } } } } fun readFileContent(fileName: String?): String? { val file = File(fileName) if (!file.exists()) { return null } var reader: BufferedReader? = null val sbf = StringBuffer() try { reader = BufferedReader(FileReader(file)) var tempStr: String? while ((reader.readLine().also { tempStr = it }) != null) { sbf.append(tempStr) } reader.close() return sbf.toString() } catch (e: IOException) { e.printStackTrace() } finally { if (reader != null) { try { reader.close() } catch (e1: IOException) { e1.printStackTrace() } } } return sbf.toString() } }