【发布时间】:2018-04-03 13:47:20
【问题描述】:
我在 Kotlin 中为 Spring WebFlux 编写了一个测试客户端和服务器。客户端向服务器发送一个数字(例如 4)并返回那么多数字(例如 0、1、2 和 3)。这是服务器实现:
class NumbersWebSocketHandler : WebSocketHandler {
override fun handle(session: WebSocketSession): Mono<Void> {
var index = 0
var count = 1
val publisher = Flux.generate<Int> { sink ->
if (index < count) {
sink.next(index)
index++
} else {
sink.complete()
}
}.map(Int::toString)
.map(session::textMessage)
.delayElements(Duration.ofMillis(500))
return session.receive()
.map(WebSocketMessage::getPayloadAsText)
.doOnNext {
println("About to send $it numbers")
count = it.toInt()
}
.then()
.and(session.send(publisher))
.then()
}
}
这里是客户端:
fun main(args: Array<String>) {
val uri = URI("ws://localhost:8080/numbers")
val client = ReactorNettyWebSocketClient()
println("How many numbers would you like?")
val input = Flux.just(readLine())
client.execute(uri) { session ->
session.send(input.map(session::textMessage))
.then(
session.receive()
.map(WebSocketMessage::getPayloadAsText)
.map { it.toInt() }
.reduce { a,b ->
println("Reduce called with $a and $b")
a + b
}
.doOnNext(::println)
.then()
)
.then()
}.block()
}
客户端成功接收数字并调用reduce,如下:
reduce 用 0 和 1 调用
reduce 用 1 和 2 调用
Reduce 用 3 和 3 调用
但是,对 doOnNext 的调用从未到达 - 大概是因为客户端不知道最后一个项目已发送。我的问题是我需要在客户端或服务器上添加什么代码才能打印总数?
更新:在服务器端关闭会话无济于事。我试过了:
.delayElements(Duration.ofMillis(500))
.doOnComplete { session.close() }
还有:
.delayElements(Duration.ofMillis(500))
.doFinally { session.close() }
但是两者都不会对客户端的行为产生任何影响。在调用“发送”之后尝试显式关闭会话也没有:
.and(session.send(publisher))
.then()
.and { session.close() }
.then()
【问题讨论】:
-
您可以使用
take()运算符,因为您知道您将收到多少物品。
标签: websocket kotlin reactive-programming spring-webflux project-reactor