在安卓应用中实现Socket通信:创建服务端和客户端

发布于:2024-05-09 ⋅ 阅读:(34) ⋅ 点赞:(0)

介绍:本文主要介绍在安卓中使用Socket创建服务端和客户端进行通信,服务端可以管理多个客户端连接,完善的异常处理,接口回调,可以满足大部分需求,更多功能自行拓展…

关于Socket套接字:

是网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

使用Socket进行网络通讯的一般步骤如下:

  1. 创建Socket对象,指定服务器的IP地址和端口号。
  2. 使用Socket对象的getInputStream()和getOutputStream()方法获取输入输出流,用于接收和发送数据。
  3. 使用输出流发送请求到服务器,使用输入流读取服务器返回的数据。
  4. 使用完毕后,通过调用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? = null
        private var bufferedReader: BufferedReader? = null

        fun 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? = null
    private var out: PrintWriter? = null
    private var reader: BufferedReader? = null
    private 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? = null
                while (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()

最后

此片文章用来记录学习,方便大家拿来即用,知识点不多,注释已经尽可能详细了,收工,下班!