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的稳定性、开启关闭时机等。以上仅供参考。