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传输数据。