该项目的目标是,让JVM (Kotlin)服务器和Python客户端通过websocket相互通信。服务器必须向客户端发送更新,客户端将处理这些更新。
服务器是一个Spring应用程序,运行服务器。客户端现在只是一个Python脚本,运行websocket客户机来连接到服务器。
正在发挥作用的是:
H 210f 211上发送消息。不起作用的是:
没有接收到来自服务器的消息
我通过连接到websocket.org的回送服务器(ws:// echo .websocket.org)尝试了客户端的接收部分,客户端接收来自服务器的回显消息。所以在我看来,问题不在客户端。
密码时间。
Kotlin服务器:用于创建websocket服务器的代码:
package nl.sajansen.screenchangenotifierserver
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Configuration
import org.springframework.messaging.handler.annotation.MessageMapping
import org.springframework.messaging.simp.SimpMessagingTemplate
import org.springframework.messaging.simp.config.MessageBrokerRegistry
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Controller
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
import org.springframework.web.socket.config.annotation.StompEndpointRegistry
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
import java.time.Instant
import java.time.format.DateTimeFormatter
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/ws").setAllowedOrigins("*")
}
override fun configureMessageBroker(config: MessageBrokerRegistry) {
config.enableSimpleBroker("/topic", "/queue")
config.setApplicationDestinationPrefixes("/app")
}
}
@Controller
class WebsocketController @Autowired constructor(val template: SimpMessagingTemplate) {
@Scheduled(fixedDelayString = "1000")
fun blastToClientsHostReport() {
println("Sending something on the websocket")
template.convertAndSend("/topic/greeting", "Hello World");
}
@MessageMapping("/greeting")
fun handle(message: String): String {
println("Received message: $message")
template.convertAndSend("/topic/greeting", message)
return "[" + getTimestamp() + ": " + message
}
}
fun getTimestamp(): String = DateTimeFormatter.ISO_INSTANT.format(Instant.now())等级依赖性等:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.1.9.RELEASE"
id("io.spring.dependency-management") version "1.0.8.RELEASE"
kotlin("jvm") version "1.2.71"
kotlin("plugin.spring") version "1.2.71"
kotlin("plugin.jpa") version "1.2.71"
kotlin("plugin.allopen") version "1.2.71" // For JPA lazy fetching
}
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.Embeddable")
annotation("javax.persistence.MappedSuperclass")
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("com.h2database:h2:1.4.197") // Fixed version as a workaround for https://github.com/h2database/h2database/issues/1841
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude(module = "junit")
exclude(module = "mockito-core")
}
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("com.ninja-squad:springmockk:1.1.2")
compile("org.springframework.boot:spring-boot-starter-websocket")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}Python客户端:
import random
import stomper as stomper
import websocket
def main():
websocket.enableTrace(True)
# Connecting to websocket
ws = websocket.create_connection("ws://localhost:8080/ws")
# Subscribing to topic
client_id = str(random.randint(0, 1000))
sub = stomper.subscribe("/topic/greeting", client_id, ack='auto')
ws.send(sub)
# Sending some message
ws.send(stomper.send("/app/greeting", "Hello there"))
while True:
print("Receiving data: ")
d = ws.recv()
print(d)
if __name__ == '__main__':
main()Pip依赖关系:
opencv-python==4.1.1.26
websocket-client==0.56.0
stomper==0.4.3控制台输出
现在,服务器的控制台输出如下。可以看到,当客户端没有连接时,就没有订户可以发送预定的消息。而客户端连接成功,并将预定的消息广播给1个订户。
Sending something on the websocket
2019-10-17 12:45:09.425 DEBUG 32285 --- [MessageBroker-3] org.springframework.web.SimpLogging : Processing MESSAGE destination=/topic/greeting session=null payload=Hello World
Sending something on the websocket
2019-10-17 12:45:10.426 DEBUG 32285 --- [MessageBroker-3] org.springframework.web.SimpLogging : Processing MESSAGE destination=/topic/greeting session=null payload=Hello World
2019-10-17 12:45:10.849 INFO 32285 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-10-17 12:45:10.850 INFO 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-10-17 12:45:10.850 DEBUG 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Detected StandardServletMultipartResolver
2019-10-17 12:45:10.855 DEBUG 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails='true': request parameters and headers will be shown which may lead to unsafe logging of potentially sensitive data
2019-10-17 12:45:10.855 INFO 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2019-10-17 12:45:10.861 DEBUG 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/ws", parameters={}
2019-10-17 12:45:10.865 DEBUG 32285 --- [nio-8080-exec-1] o.s.w.s.s.s.WebSocketHandlerMapping : Mapped to org.springframework.web.socket.server.support.WebSocketHttpRequestHandler@27a9f025
2019-10-17 12:45:10.872 DEBUG 32285 --- [nio-8080-exec-1] o.s.w.s.s.s.WebSocketHttpRequestHandler : GET /ws
2019-10-17 12:45:10.885 DEBUG 32285 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 101 SWITCHING_PROTOCOLS
2019-10-17 12:45:10.901 DEBUG 32285 --- [nio-8080-exec-1] s.w.s.h.LoggingWebSocketHandlerDecorator : New StandardWebSocketSession[id=393fc3cd-9ca3-1749-1ea8-541def6592e0, uri=ws://localhost:8080/ws]
2019-10-17 12:45:10.912 DEBUG 32285 --- [nboundChannel-2] org.springframework.web.SimpLogging : Processing SUBSCRIBE /topic/greeting id=216 session=393fc3cd-9ca3-1749-1ea8-541def6592e0
2019-10-17 12:45:10.914 DEBUG 32285 --- [nboundChannel-7] .WebSocketAnnotationMethodMessageHandler : Searching methods to handle SEND /app/greeting session=393fc3cd-9ca3-1749-1ea8-541def6592e0 text/plain payload=Hello there, lookupDestination='/greeting'
2019-10-17 12:45:10.915 DEBUG 32285 --- [nboundChannel-7] .WebSocketAnnotationMethodMessageHandler : Invoking nl.sajansen.screenchangenotifierserver.WebsocketController#handle[1 args]
Received message: Hello there
2019-10-17 12:45:10.916 DEBUG 32285 --- [nboundChannel-7] org.springframework.web.SimpLogging : Processing MESSAGE destination=/topic/greeting session=null payload=Hello there
2019-10-17 12:45:10.916 DEBUG 32285 --- [nboundChannel-7] org.springframework.web.SimpLogging : Broadcasting to 1 sessions.
2019-10-17 12:45:10.919 DEBUG 32285 --- [nboundChannel-7] org.springframework.web.SimpLogging : Processing MESSAGE destination=/topic/greeting session=393fc3cd-9ca3-1749-1ea8-541def6592e0 payload=[2019-10-17T10:45:10.917Z: Hello there
2019-10-17 12:45:10.919 DEBUG 32285 --- [nboundChannel-7] org.springframework.web.SimpLogging : Broadcasting to 1 sessions.
Sending something on the websocket
2019-10-17 12:45:11.427 DEBUG 32285 --- [MessageBroker-3] org.springframework.web.SimpLogging : Processing MESSAGE destination=/topic/greeting session=null payload=Hello World客户端的输出是这样的,但只能等到世界末日才能接收到以下消息:
--- request header ---
GET /ws HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:8080
Origin: http://localhost:8080
Sec-WebSocket-Key: 8ihHk0C5C0nji4s7u4atZQ==
Sec-WebSocket-Version: 13
-----------------------
--- response header ---
HTTP/1.1 101
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: Drq8+/vJkXkvToB3/AuCGMdYwuo=
Date: Thu, 17 Oct 2019 10:45:10 GMT
-----------------------
send: b'\x81\xb9\x88k\xa6j\xdb>\xe49\xcb9\xef(\xcda\xcf\x0e\xb2Y\x97\\\x82\x0f\xc3\x19\xfc\x02\xc8\x0b\xfc\x02\xc9\x04\xb2D\xd2\x05\xf8\x02\xc5E\xef\x19\xc3\x0f\xfc\x02\xc8\r\x82\n\xc5\x01\xb2\n\xd3\x1e\xe7a\xacj\x82'
send: b'\x81\xc5\xd0\x8dE6\x83\xc8\x0br\xda\xe9 E\xa4\xe4+W\xa4\xe4*X\xea\xa2$F\xa0\xa2"D\xb5\xe81_\xbe\xeaOU\xbf\xe31S\xbe\xf9hB\xa9\xfd \x0c\xa4\xe8=B\xff\xfd)W\xb9\xe3O<\x98\xe8)Z\xbf\xad1^\xb5\xff 6\xda'
Receiving data:如果您有更好的想法,请提供更多的背景信息:更新将包含一个图像文件(可能编码为base64)。更新必须接近实时发送(允许延迟不超过1秒)。这些更新的间隔可以从几分钟到半秒不等。客户机和服务器是同一网络中的两台不同的机器,但该网络的吞吐量有限。
那么,谁能发现出了什么问题呢?
我读过这篇关于websockets的文档的大部分内容,但我看不出出了什么问题:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket
This answer也帮了我很大的忙,但是这个例子本身并没有起作用(在将while not True修改为while True之后)。
Update18 2019年10月18日:我寻找了一个SocketJS客户机,因为我让Kotlin服务器部分与SocketJS和JavaScript客户端一起工作。但我找不到任何Python SocketJS客户端实现。我想知道剩下的唯一解决方案是否是在Python应用程序(客户端)中启动websocket服务器,并让客户机将其websocket服务器的详细信息发送到Kotlin服务器,然后Kotlin服务器将连接到客户端的websocket服务器。这不是一个很好的解决方案,但我不知道它是否会奏效。我会随时通知你的。
更新2021年2月1日:我没有在这个问题上花费更多的时间。但我会让这个帖子,以防有人搞清楚这一点,并能帮助其他人的解决方案。
发布于 2021-04-30 19:55:29
上个月我也面临着同样的问题。我假设您正在为Python使用。提到Websocket Client not receiving any messages,我认为您忘记启动连接了。
因此,您应该更改您的python客户端代码。
...
# Connecting to websocket
ws = websocket.create_connection("ws://localhost:8080/ws")
# Subscribing to topic
client_id = str(random.randint(0, 1000))
sub = stomper.subscribe("/topic/greeting", client_id, ack='auto')
ws.send(sub)
...进入到这个
# Connecting to websocket
ws = websocket.create_connection("ws://localhost:8080/ws")
# Initate Stomp connection!
ws.send("CONNECT\naccept-version:1.0,1.1,2.0\n\n\x00\n")
# Subscribing to topic
client_id = str(random.randint(0, 1000))
sub = stomper.subscribe("/topic/greeting", client_id, ack='auto')
ws.send(sub)我希望它能成功。
尽管如此,我还是通过从WebSocketApp库实现import websocket类来解决这个问题,而不是执行像代码这样的过程步骤。
https://stackoverflow.com/questions/58430980
复制相似问题