如何保持 Kotlin Ktor websocket 处于打开状态
Posted
技术标签:
【中文标题】如何保持 Kotlin Ktor websocket 处于打开状态【英文标题】:How to keep a Kotlin Ktor websocket open 【发布时间】:2021-03-26 14:34:51 【问题描述】:创建了一个 ktor 服务器 websocket 端点。
尽管处于while (true)
循环中,但它拒绝保持打开状态:
服务器
routing
webSocket("/data")
while (true)
send(Frame.Text("Howdy"))
delay(5000)
客户端(浏览器)
const ws = new WebSocket("ws://www.example.com:1234/data")
客户端(浏览器)连接并接收消息,但随后套接字关闭。
为什么这个 ws 一直关闭?我从未发出过“关闭”命令。如何保持打开状态,以便发送新的排队消息?
参考: https://ktor.io/docs/servers-features-websockets.html#usage
【问题讨论】:
【参考方案1】:我的猜测是您没有在客户端 websocket 上注册侦听器,一旦建立连接,由于没有侦听器而断开连接。或者可能正在接收消息,但您需要通过注册显式侦听器将它们输出到某个地方。
为了测试您的代码,我尝试了this Ktor WebSocket Chat tutorial。我首先克隆 the sample repository 并使用 IntelliJ IDEA CE 打开服务器文件夹。然后,我打开了Application.kt
文件并用以下几行替换了 Application 模块,与您的示例非常相似:
@Suppress("unused")
fun Application.module()
install(WebSockets)
routing
webSocket("/data")
send("You are connected!")
while (true)
send(Frame.Text("Howdy"))
delay(1_000)
那个教程在第 3 章告诉你打开an html echo websocket client,但这对我不起作用,它总是说ERROR: undefined
(我猜是因为偏执的网络权限?)。但是,在该网页的底部,有一个连接到 websocket 的示例 HTML 代码,它工作正常!我复制了示例并稍作修改,将以下行放入test.html
文件中:
<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Test</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:8080/data";
var output;
function init()
output = document.getElementById("output");
testWebSocket();
window.setTimeout(delayedTest, 5000);
function delayedTest()
websocket.close();
//alert("delayed");
function testWebSocket()
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) onOpen(evt) ;
websocket.onclose = function(evt) onClose(evt) ;
websocket.onmessage = function(evt) onMessage(evt) ;
websocket.onerror = function(evt) onError(evt) ;
function onOpen(evt)
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
function onClose(evt)
writeToScreen("DISCONNECTED");
function onMessage(evt)
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
//websocket.close();
function onError(evt)
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
function doSend(message)
writeToScreen("SENT: " + message);
websocket.send(message);
function writeToScreen(message)
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
一旦您运行了 ktor websocket 服务器,打开该 HTML 文件就会向我显示以下行,这表明连接已建立,因为服务器会定期发送 Howdy
消息,直到 HTML javascript 超时触发并关闭套接字:
CONNECTED
SENT: WebSocket rocks
RESPONSE: Howdy
RESPONSE: Howdy
RESPONSE: Howdy
RESPONSE: Howdy
RESPONSE: Howdy
DISCONNECTED
编辑更新:为了测试套接字是否没有接收消息,或者它正在接收消息但没有打印它们,我在我的test.html
文件中进一步修改了testWebSocket()
以包含以下行:
function testWebSocket()
websocket = new WebSocket(wsUri);
//websocket.onopen = function(evt) onOpen(evt) ;
//websocket.onclose = function(evt) onClose(evt) ;
//websocket.onmessage = function(evt) onMessage(evt) ;
//websocket.onerror = function(evt) onError(evt) ;
这些行相当于您的原始代码,我没有得到任何答案。但是,如果我打开 Safari 网络调试面板并单击 data 流,我可以看到在超时显式关闭套接字之前 HTML 页面仍然接收Howdy
事件。
【讨论】:
以上是关于如何保持 Kotlin Ktor websocket 处于打开状态的主要内容,如果未能解决你的问题,请参考以下文章
如何使用内容协商将 json 转换为 ktor 中的 kotlin 对象?
Kotlin Multiplatform Mobile:Ktor - 如何在 Kotlin Native(iOS)中取消活动协程(网络请求、后台工作)?
如何在 Ktor (Kotlin) 中管道的各个部分之间传递数据