介绍:本文主要介绍在安卓中使用Socket创建服务端和客户端进行通信,服务端可以管理多个客户端连接,完善的异常处理,接口回调,可以满足大部分需求,更多功能自行拓展…
关于Socket套接字:
是网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
使用Socket进行网络通讯的一般步骤如下:
- 创建Socket对象,指定服务器的IP地址和端口号。
- 使用Socket对象的getInputStream()和getOutputStream()方法获取输入输出流,用于接收和发送数据。
- 使用输出流发送请求到服务器,使用输入流读取服务器返回的数据。
- 使用完毕后,通过调用Socket对象的close()方法关闭Socket连接。
创建Socket服务端
功能包括启动服务,关闭连接,发送消息,接收消息,管理客户端,将事件回调给外界等
class SocketServer(private val port: Int, private val listener: SocketServerListener? = null) : Thread() {private val TAG = "SocketServer"private lateinit var serverSocket: ServerSocket // serverSocket 对象private val clientHandlers = mutableListOf<ClientHandler>() // 存储每个客户端线程private val executor = Executors.newSingleThreadExecutor()override fun run() {startServer()}// 启动服务器的方法private fun startServer() {try {serverSocket = ServerSocket(port)Log.i(TAG, "Server is running on port $port")while (!isInterrupted) {val clientSocket = serverSocket.accept() // 接受客户端连接listener?.onClientConnected(clientSocket) // 通知客户端已连接val clientThread = ClientHandler(clientSocket, listener) // 为每个客户端创建一个新的线程clientThread.start()clientHandlers.add(clientThread) // 安全地添加 Handler 到列表}} catch (e: Exception) {listener?.onError(e)}}// 关闭服务器的方法fun stopServer() {clientHandlers.forEach { it.closeConnection() } // 关闭所有客户端线程try {serverSocket.close() // 关闭 ServerSocket} catch (e: Exception) {e.printStackTrace()}}// 当线程被中断时,关闭服务器override fun interrupt() {stopServer()super.interrupt()}// 定义处理每个客户端连接的线程class ClientHandler(private val socket: Socket, private val listener: SocketServerListener? = null) : Thread() {private var printWriter: PrintWriter? = nullprivate var bufferedReader: BufferedReader? = nullfun sendMessage(msg: String) {if (printWriter != null) {synchronized(printWriter!!) {printWriter?.println(msg)}}}override fun run() {printWriter = PrintWriter(socket.getOutputStream(), true)bufferedReader = BufferedReader(InputStreamReader(socket.getInputStream()))try {var message: String? = null// 服务端接收数据while (socket.isConnected && bufferedReader?.readLine().also { message = it } != null) {// 当接收到消息时,通过 listener 通知外部listener?.onMessageReceived(message!!)// 回应客户端//printWriter?.println("Received: $message")}} catch (e: IOException) {listener?.onError(e)e.printStackTrace()} finally {// 确保最后会关闭连接closeConnection()}}// 关闭连接的方法fun closeConnection() {try {socket.close() // 关闭 socket 连接printWriter?.close()bufferedReader?.close()} catch (e: IOException) {listener?.onError(e)}Log.d("ClientHandler", "Client disconnected ${socket.inetAddress.hostAddress}")listener?.onClientDisconnected(socket) // 通知外部客户端已断开}}// 发送消息到客户端的方法fun sendMessage(message: String) {executor.submit {clientHandlers.forEach {it.sendMessage(message)}}}
}// 定义一个接口,用于接收消息和通知客户端连接和断开
interface SocketServerListener {fun onMessageReceived(message: String)fun onClientConnected(client: Socket)fun onClientDisconnected(client: Socket)fun onError(e: Exception)
}
创建Socket客户端
功能包括建立连接,关闭连接,发送消息,接收消息,异常处理,将事件回调给外界等
class SocketClient(private val serverAddress: String,private val serverPort: Int,private val listener: SocketClientListener?
) {private var socket: Socket? = nullprivate var out: PrintWriter? = nullprivate var reader: BufferedReader? = nullprivate val executor = Executors.newSingleThreadExecutor()private val connectLatch = CountDownLatch(1)fun connect() {executor.execute {try {socket = Socket(serverAddress, serverPort)out = PrintWriter(socket!!.getOutputStream(), true)reader = BufferedReader(InputStreamReader(socket!!.getInputStream()))listener?.onConnected()connectLatch.countDown() // 通知已经连接} catch (e: IOException) {listener?.onConnectionFailed(e)}}}fun sendMessage(message: String) {executor.execute {connectLatch.await() // 等待连接完成out?.println(message)}}fun receiveMessages() {executor.execute {try {connectLatch.await() // 等待连接完成var message: String? = nullwhile (reader?.readLine().also { message = it } != null) {listener?.onMessageReceived(message!!)}} catch (e: IOException) {listener?.onError(e)}}}fun close() {executor.execute {try {// socket 和 reader 关闭顺序不能变,否则会阻塞在 reader?.close()socket?.close()reader?.close()out?.close()listener?.onDisconnected()} catch (e: IOException) {listener?.onError(e)}}}
}interface SocketClientListener {fun onConnected()fun onMessageReceived(message: String)fun onConnectionFailed(e: Exception)fun onDisconnected()fun onError(e: Exception)
}
获取IP地址
public static String getIPAddress() {try {List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());for (NetworkInterface intf : interfaces) {List<InetAddress> addrs = Collections.list(intf.getInetAddresses());for (InetAddress addr : addrs) {if (!addr.isLoopbackAddress() && addr instanceof Inet4Address) {return addr.getHostAddress();}}}} catch (Exception e) {Log.e("getIPAddress", e.toString());}return "";}
如何使用
服务端:
val listener = object : SocketServerListener {override fun onMessageReceived(message: String) {XLog.i(" SocketServerListener Message received from client: $message")}override fun onClientConnected(client: Socket) {XLog.i(" SocketServerListener Client connected: ${client.inetAddress.hostAddress}")}override fun onClientDisconnected(client: Socket) {XLog.i(" SocketServerListener disconnected: ${client.inetAddress.hostAddress}")}override fun onError(e: Exception) {XLog.i(" SocketServerListener onError: ${e.message}")}}server = SocketServer(12345, listener)server.start()
客户端:
val client = SocketClient(getIPAddress(), 12345, object : SocketClientListener {override fun onConnected() {XLog.i(" SocketClientListener onConnected")}override fun onMessageReceived(message: String) {XLog.i(" SocketClientListener onMessageReceived: $message")}override fun onConnectionFailed(e: Exception) {XLog.i(" SocketClientListener onConnectionFailed: ${e.message}")}override fun onDisconnected() {XLog.i(" SocketClientListener onDisconnected")}override fun onError(e: Exception) {XLog.i(" SocketClientListener onError")}})client.connect()client.sendMessage("Hello, server!")client.sendMessage("啊哈哈哈 鸡汤来喽!!!")client.receiveMessages()
最后
此片文章用来记录学习,方便大家拿来即用,知识点不多,注释已经尽可能详细了,收工,下班!