如何使用Websockets建立一个多用户的聊天应用程序

106 阅读4分钟

Websocket是客户端和服务器之间发送和接收数据的双向通信协议。

它通过TCP/IP套接字连接在HTTP上运行。它用于在客户端和服务器之间传递信息。

我们可以使用WebSockets建立一个多用户聊天应用程序。

为了连接客户端和服务器,我们已经创建了一个WebSocketManger类。

OkHttpClient用于连接目的。

第1步:安装Okhttp

在build.gradle中添加依赖性

实现 "com.squareup.okhttp3:okhttp:4.2.2

第2步:添加互联网权限

在清单中添加权限

第3步:编写代码

OkHttpClient是用来发送HTTP请求的。为了认证的目的,我们使用了一个头和使用访问令牌的url。

     fun init(url: String, _messageListener: MessageListener) {

        client = OkHttpClient.Builder()

            .build()

        request = Request.Builder().url(url).addHeader(

            "Authorization", "Bearer " + ACCESS_TOKEN).build()

        messageListener = _messageListener

     }

接下来是通过一个网络套接字连接网址,我们使用OkHttpClient new WebSocket使用请求来连接一个新的网络套接字。我们将在上述方法被调用后调用connect函数。

这里createlistener是websocketlistener的一个函数。

fun connect() {

        if (isConnect()) {

            return

        }

        client.newWebSocket(request, createListener())

    }

为了重新连接websocket,我们还通过检查它是否已经连接,创建了一个重新连接函数。

  fun reconnect() {

        if (connectNum <= MAX_NUM) {

            try {

                Thread.sleep(MILLIS.toLong())

                connect()

                connectNum++

            } catch (e: InterruptedException) {

                e.printStackTrace()

            }

        }

    }


fun isConnect(): Boolean {

        return isConnect

    }  

这些是用于通过服务器向客户端发送消息的函数。 使用的 是*'发送'* 函数。 最重要的是,我们需要有一个消息格式,以便我们能够连接、发送和接收数据;否则,套接字会自动断开连接。我们必须预先定义发送消息格式,以便在客户端和服务器之间共享数据。

fun sendMessage(text: String): Boolean {

        return if (!isConnect()) false else mWebSocket.send(text)

    }


    fun sendMessage(byteString: ByteString): Boolean {

        return if (!isConnect()) false else mWebSocket.send(byteString)


这个函数是用来关闭套接字之间的连接的。为了避免任何问题,我们将检查WebSocket是否已连接。

cancel() 方法被立即调用,并猛烈地释放这个Web socket所持有的资源,丢弃任何排队的消息。如果Web套接字已经被关闭或取消了,这不会有任何作用。

fun close() {

        if (isConnect()) {

            mWebSocket.cancel()

            mWebSocket.close(1001, "to close socket")

        }

    }

WebSocket消息是由接口.即WebSocketListener处理的。它有相应的函数来执行所调用的事件。生命周期的一个实例被管理。

onOpen 方法在WebSocket被远程对等体接受并可以开始传输消息时被调用。

onMessage 方法是在WebSocket已经收到消息时调用的。

有两个onMessage方法,一个是接收字符串格式的消息,另一个是接收byteString格式的消息。

onClosing 方法被调用以关闭客户端和服务器之间的连接。

onFailure 方法在客户端和服务器之间的连接失败时被调用。

private fun createListener(): WebSocketListener {

        return object : WebSocketListener() {

            override fun onOpen(

                webSocket: WebSocket,

                response: Response

            ) {

                super.onOpen(webSocket, response)

               mWebSocket = webSocket

                isConnect = response.code == 101

                if (!isConnect) {

                    reconnect()

                } else {

                    messageListener.onConnectSuccess()

                }

             }



            override fun onMessage(webSocket: WebSocket, text: String) {

                super.onMessage(webSocket, text)

                messageListener.onMessage(text)

            }



            override fun onMessage(webSocket: WebSocket, bytes: ByteString) {

                super.onMessage(webSocket, bytes)

                messageListener.onMessage(bytes.base64())

            }


            override fun onClosing(

                webSocket: WebSocket,

                code: Int,

                reason: String

            ) {

                super.onClosing(webSocket, code, reason)

                isConnect = false

                messageListener.onClose()

            }


            override fun onClosed(

                webSocket: WebSocket,

                code: Int,

                reason: String

            ) {

                super.onClosed(webSocket, code, reason)

                isConnect = false

                messageListener.onClose()

            }


            override fun onFailure(

                webSocket: WebSocket,

                t: Throwable,

                response: Response?

            ) {

                super.onFailure(webSocket, t, response)

                if (response != null) {

                 isConnect = false

                messageListener.onConnectFailed()

                messageListener.onClose()

            }

        }

    }

}

以下是WebSocket管理器的完整代码

object WebSocketManager {

    private val TAG = WebSocketManager::class.java.simpleName

    private const val MAX_NUM = 5

     private const val MILLIS = 5000 

    private lateinit var client: OkHttpClient

    private lateinit var request: Request

    private lateinit var messageListener: MessageListener

    private lateinit var mWebSocket: WebSocket

    private var isConnect = false

    private var connectNum = 0

    fun init(url: String, _messageListener: MessageListener) {

        client = OkHttpClient.Builder()

            .build()

        request = Request.Builder().url(url).addHeader(

            "Authorization", "Bearer " +    ACCESS_TOKEN ).build()

        messageListener = _messageListener

    }


    fun connect() {

        if (isConnect()) {

            return

        }

        client.newWebSocket(request, createListener())

     //   client.dispatcher.executorService.shutdown()

    }


    fun reconnect() {

        if (connectNum <= MAX_NUM) {

            try {

                Thread.sleep(MILLIS.toLong())

                connect()

                connectNum++ }

 catch (e: InterruptedException) {

                e.printStackTrace()

            }  }  }


    fun isConnect(): Boolean {

        return isConnect

    }


    fun sendMessage(text: String): Boolean {

        return if (!isConnect()) false else mWebSocket.send(text)

    }


    fun sendMessage(byteString: ByteString): Boolean {

        return if (!isConnect()) false else mWebSocket.send(byteString)

    }


    fun close() {

        if (isConnect()) {

            mWebSocket.cancel()

            mWebSocket.close(1001, "to close socket")

        }

    }


    private fun createListener(): WebSocketListener {

        return object : WebSocketListener() {

            override fun onOpen(

                webSocket: WebSocket,

                response: Response

            ) {

                super.onOpen(webSocket, response)

                 mWebSocket = webSocket

                isConnect = response.code == 101

                if (!isConnect) {

                    reconnect()

                } else {

                    logE(TAG, "connect success.")

                    messageListener.onConnectSuccess()

                }

            }


            override fun onMessage(webSocket: WebSocket, text: String) {

                super.onMessage(webSocket, text)

                messageListener.onMessage(text)

            }



            override fun onMessage(webSocket: WebSocket, bytes: ByteString) {

                super.onMessage(webSocket, bytes)

                messageListener.onMessage(bytes.base64())

            }


            override fun onClosing(

                webSocket: WebSocket,

                code: Int,

                reason: String

            ) {

                super.onClosing(webSocket, code, reason)

                isConnect = false

                messageListener.onClose()

            }


            override fun onClosed(

                webSocket: WebSocket,

                code: Int,

                reason: String

            ) {

                super.onClosed(webSocket, code, reason)

                 isConnect = false

                messageListener.onClose()

            }


            override fun onFailure(

                webSocket: WebSocket,

                t: Throwable,

                response: Response?

            ) {

                super.onFailure(webSocket, t, response)

                if (response != null) {

               //  "connect failed “

                )

                isConnect = false

                messageListener.onConnectFailed()

                messageListener.onClose()

            }

        }

    }

}

以下是如何用init方法和connect方法启动WebSocket的例子

WebSocketManager.init("$CHAT_SERVER_URL"}", this)

WebSocketManager.connect()

在我们收到连接成功的消息后,要向客户端发送消息,请调用已在服务器端定义好格式的发送消息方法来传输数据。

WebSocketManager.sendMessage(text)

操作完成后,我们可以调用关闭方法。

WebSocketManager.close()

这是与客户端和服务器通信的最简单、最容易的方法,以使用WebSocket传输数据。