IPC之Socket

2019-12-17  本文已影响0人  钦_79f7

参考Android开发艺术探索

Socket

Socket:套接字,网络通信值的概念,分为流式套接字和用户数据套接字两种。

代码实现

权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

服务端

class TCPServerService : Service() {

    private var mIsServiceDestroyed = false

    private val mDefinedMessages = arrayOf("你好啊,洒洒水所", "今天上海听爱情", "我屮艸芔茻", "你这人真尼玛操蛋", "j今Tina踩了一坨屎")

    private val mTCPServerThread = Thread(Runnable {
        //监听本地8688 端口
        val serverSocket = ServerSocket(8688)
        //循环接收客户端的连接请求,用来支持多个客户端连接
        while (!mIsServiceDestroyed) {
            val client = serverSocket.accept()
            println("accept")
            //每接收到一个客户端的连接请求之后,开启一个线程用来处理客户端的消息
            Thread(Runnable { responseClient(client) }).start()
        }
    })

    override fun onCreate() {
        super.onCreate()
        mTCPServerThread.start()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onDestroy() {
        mIsServiceDestroyed = true
        super.onDestroy()
    }

    /**
     * 接收客户端的消息,并向客户端灰回复消息
     */
    private fun responseClient(client: Socket) {
        val reader = BufferedReader(InputStreamReader(client.getInputStream()))
        val writer = PrintWriter(BufferedWriter(OutputStreamWriter(client.getOutputStream())), true)
        writer.println("欢迎来到聊天室!")
        //循环接收当前线程对应的客户端发来消息,并回复
        while (!mIsServiceDestroyed) {
            val str: String? = reader.readLine()
            println("msg from client : $str")
            if (str == null) {
                break
            }
            val i = Random().nextInt(mDefinedMessages.size)
            writer.println(mDefinedMessages[i])
            println(mDefinedMessages[i])
        }
        //循环结束后,关闭操作
        println("client quit.")
        reader.close()
        writer.close()
        client.close()
    }
}

客户端

class TCPClientActivity : AppCompatActivity() {
    companion object {
        private const val MSG_RECEIVE_NEW_MSG = 1
        private const val MSG_SOCKET_CONNECTED = 2
    }

    private var mClientSocket: Socket? = null
    private var mPrintWriter: PrintWriter? = null

    @SuppressLint("SetTextI18n")
    private val mHandler = Handler(Handler.Callback {
        when (it.what) {
            MSG_RECEIVE_NEW_MSG -> tvMsgContainer.text = tvMsgContainer.text.toString() + it.obj
            MSG_SOCKET_CONNECTED -> btnSend.isEnabled = true
        }
        true
    })

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_tcpclient)

        btnSend.setOnClickListener { clickBtnSend() }

        startService(Intent(act, TCPServerService::class.java))

        Thread(Runnable { connectTCPServer() }).start()
//        btnSend.postDelayed({  }, 3000)//延迟连接,等待服务端启动完成
    }

    private fun connectTCPServer() {

        var socket: Socket? = null
        while (socket == null) {
            //通过循环来处理服务端启动延迟的问题,当然这里的循环也是基于处理失败重连的机制上的
            //如果不做try catch 处理,当连接失败时会抛错
            try {
                socket = Socket("localhost", 8688)
                mClientSocket = socket
                mPrintWriter = PrintWriter(BufferedWriter(OutputStreamWriter(socket.getOutputStream())), true)
                mHandler.sendEmptyMessage(MSG_SOCKET_CONNECTED)
                println("connect server success")
            } catch (e: Exception) {
                SystemClock.sleep(1000)
                println("connect server failed, retry...")
            }
        }

        val br = BufferedReader(InputStreamReader(socket.getInputStream()))
        while (!isFinishing) {
            var msg: String? = null
            try {
                msg = br.readLine()
            } catch (e: Exception) {
                e.printStackTrace()
            }
            if (msg != null) {
                val time = formatDateTime(System.currentTimeMillis())
                val showedMsg = "server $time: $msg\n"
                mHandler.obtainMessage(MSG_RECEIVE_NEW_MSG, showedMsg).sendToTarget()
            }
        }

        println("quit...")
        mPrintWriter?.close()
        br.close()
        socket.close()
    }

    private fun formatDateTime(time: Long): String {
        return SimpleDateFormat("(HH:mm:ss)", Locale.CHINA).format(Date(time))
    }

    @SuppressLint("SetTextI18n")
    private fun clickBtnSend() {
        val msg: String? = inputMsg.text.toString()
        if (!msg.isNullOrEmpty()) {
            mPrintWriter?.println(msg)
            inputMsg.setText("")
            val time = formatDateTime(System.currentTimeMillis())
            val showedMsg = "self $time : $msg\n"
            tvMsgContainer.text = tvMsgContainer.text.toString() + showedMsg
        }
    }

    override fun onDestroy() {
        mClientSocket?.shutdownInput()
        mClientSocket?.close()
        mHandler.removeCallbacksAndMessages(null)        
        super.onDestroy()
    }
}

AndroidManifest

        <service
            android:name=".demo.socket.TCPServerService"
            android:process=":tcp_server" />

        <activity
            android:name=".demo.socket.TCPClientActivity"
            android:windowSoftInputMode="adjustResize" />
上一篇 下一篇

猜你喜欢

热点阅读