Kotlin进程通信------Socket

Posted 战国剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin进程通信------Socket相关的知识,希望对你有一定的参考价值。

Socket作为进程通信的一种方式,在日常的进程通信中使用的不频繁,它更常用的是即时通讯、跨设备的一对多场景等。android进程间通信中使用socket,一般是一对一的场景,是常用Socket方式的降级、简单化的使用方式。

Socket的使用,需要了解、注意的是它的握手、挥手机制。

简洁明了的,可以参考:

为什么不能用两次握手进行连接?

为什么socket是三次握手挥手却是四次

详细解释的,可以参考:HTTP、HTTPS、TCP/IP、Socket通信、三次握手四次挥手过程?

回到android socket进程通信场景。我们要做的还是和前几篇类似,做一个简易工程,来实现通信:这里需要一个client(socket)客户端、一个server(socket server)服务端。

一、server(socket server)服务端

如下代码:我们定义了一个Service形式的服务端:

1、在此处我们没有使用onBind了;

2、新开线程,开启ServerSocket,监听9999这个端口,等待客户端的连接请求;

3、accept是阻塞式的,需要在线程中等待;

4、readLine方式获取客户端数据。当客户端关闭后,客户端会发过来的数据null。所以有这么一个判空跳出,关闭服务;


class SocketServer : Service() {

    var serverAllowed :Boolean = true

    private var runnable = Runnable {
        val serverSocket:ServerSocket = ServerSocket(9999)
        val accept:Socket = serverSocket.accept()
        Thread { response(accept) }.start()
    }

    override fun onCreate() {
        super.onCreate()
        Thread(runnable).start()
    }
    override fun onBind(intent: Intent?): IBinder? {
        TODO("Not yet implemented")
    }

    private fun response(accept: Socket) {
        try {
            //从客户端接收的信息
            val bufferedReaderIn: BufferedReader = BufferedReader(InputStreamReader(accept.getInputStream()))
            //发送信息给客户端
            val out:PrintWriter = PrintWriter(BufferedWriter(OutputStreamWriter(accept.getOutputStream())),true)
            while (serverAllowed){
                val msg = bufferedReaderIn.readLine()
                if(TextUtils.isEmpty(msg)){
                    println("收到客户端的信息为空,断开连接")
                    break
                }
                println("收到客户端的信息: $msg")
                val msgOp = "加工从客户端的信息: $msg"
                out.println(msgOp);
            }
            println("关闭服务")
            bufferedReaderIn.close()
            out.close()
            accept.close()

        }catch (e:Exception){
            println(e.message)
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        serverAllowed = false
    }
}

服务写好后,只要启动该服务就可以:

 startService(Intent(this, SocketServer::class.java))

二、client(socket)客户端

如下代码,如果省略异常处理的话,可以用一句话概括下:新建socket对象,在socket对象基础上,新建发送和接收对象,操作发送和接收对象做相应的操作。

此处,我们做的操作是,每1秒向服务端发送和接收数据。

注意:以下代码需要在线程中调用,因为readLine也是阻塞的方法。

private fun connectSocketServer() {
        var read: BufferedReader? = null
        var write: PrintWriter? = null
        var socket: Socket? = null
        try {
            if (socket == null) {
                socket = Socket("localhost", 9999)
            }
            while (!isFinishing()) {
                //1、发送数据
                if (write == null) {
                    write = PrintWriter(
                        BufferedWriter(OutputStreamWriter(socket.getOutputStream())),
                        true
                    ) //发送数据
                }
                write.println("客户端发出信息")

                //2、 接收服务器端的消息
                if (read == null) {
                    read = BufferedReader(InputStreamReader(socket.getInputStream()))
                }
                val msg: String = read.readLine()
                println("客户端接收信息:$msg")
                SystemClock.sleep(1000)
            }
            println("客户端关闭")
        } catch (e: Exception) {
           println(e.message)
        } finally {
            read?.close()
            write?.close()
            socket?.close()
        }
    }

最后,还是要加上权限与service声明。

<service
            android:name=".socket.SocketServer"
            android:label="@string/socket_name"
            android:process=":socket_remote">
        </service>
<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

原理通过工程可以体现,如果需要真实在线上运行,还需要做优化:socket的稳定性、开启关闭时机等。以上仅供参考。

以上是关于Kotlin进程通信------Socket的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin进程通信------Socket

13.2进程的通信:QueuePipe

kotlin简单实现AIDL进程间通信

kotlin简单实现AIDL进程间通信

Android socket编程

Kotlin进程通信------Messenger