WebSocketSession.send 不做任何事情
Posted
技术标签:
【中文标题】WebSocketSession.send 不做任何事情【英文标题】:WebSocketSession.send does not do anything 【发布时间】:2021-12-30 12:59:39 【问题描述】:我正在编写一个游戏,当一个玩家结束其回合时,我想通知对手轮到他玩了。
所以我将 WebSocketSessions 存储在“Player”类中,所以我只需要获取一个玩家的实例就可以访问他的 websocketsession。
问题是当我使用存储在“播放器”实例中的 websocketsession 的“发送”方法时,什么都没有发生。
这是我将 WebSocketSession 存储在播放器对象中的代码,它实际上从前端正确接收消息,并且能够发回消息并且它可以工作:
@Component("ReactiveWebSocketHandler")
public class ReactiveWebSocketHandler implements WebSocketHandler
@Autowired
private AuthenticationService authenticationService;
@Override
public Mono<Void> handle(WebSocketSession webSocketSession)
Flux<WebSocketMessage> output = webSocketSession.receive()
.map(msg ->
String payloadAsText = msg.getPayloadAsText();
Account account = authenticationService.getAccountByToken(payloadAsText);
Games.getInstance().getGames().get(account.getIdCurrentGame()).getPlayerById(account.getId()).setSession(webSocketSession);
return "WebSocketSession id: " + webSocketSession.getId();
)
.map(webSocketSession::textMessage);
return webSocketSession
.send(output);
这是我用来通知对手玩家轮到该玩的代码了,“opponentSession.send”方法似乎没有产生任何结果,没有错误消息,看起来我什么也没收到前端。会话的 ID 与 handle 方法中的相同,所以我认为会话对象很好,当我进行测试时,websocket 会话也已打开并准备就绪:
@RequestMapping(value = "/game/endTurn", method = RequestMethod.POST)
GameBean endTurn(
@RequestHeader(value = "token", required = true) String token)
ObjectMapper mapper = new ObjectMapper();
Account account = authenticationService.getAccountByToken(token);
gameService.endTurn(account);
Game game = gameService.getGameByAccount(account);
//GameBean opponentGameBean = game.getOpponentGameState(account.getId());
//WebSocketMessage webSocketMessage = opponentSession.textMessage(mapper.writeValueAsString(opponentGameBean));
WebSocketSession opponentSession = game.getPlayerById(game.getOpponentId(account.getId())).getSession();
WebSocketMessage webSocketMessage = opponentSession.textMessage("test message");
opponentSession.send(Mono.just(webSocketMessage));
return gameService.getGameStateByAccount(account);
您可以在屏幕截图中看到,handle 方法工作正常,我可以发送和接收消息。 Websocket input and output
有人知道我怎样才能让对手Session.send 方法正常工作,以便我可以在前端接收消息吗?
【问题讨论】:
你不应该混合使用 webflux 和 spring web。如果这样做,spring 服务器将启动一个 spring web 应用程序,而您将无法从响应式应用程序中获得好处。 【参考方案1】:您正在为您的 websocket 使用响应式堆栈,WebSocketSession#send 返回一个 Mono<Void>
,但您没有订阅此 Mono(您只是组装了它),所以在订阅它之前什么都不会发生。
在您的端点中,您似乎没有使用 webflux,因此您处于同步世界中,因此您别无选择,只能block
opponentSession.send(Mono.just(webSocketMessage)).block();
如果您使用的是 webflux,那么您应该更改您的方法以返回 Mono 并执行以下操作:
return opponentSession.send(Mono.just(webSocketMessage)).then(gameService.getGameStateByAccount(account));
如果您对此不熟悉,请查看projectreactor 和WebFlux
【讨论】:
感谢您的回答! “块”方法导致错误,这是因为我认为我正在混合 REST api 和 webflux。我用过:对手Session.send(Mono.just(webSocketMessage)).subscribe();它工作得很好。非常感谢您的帮助,我想我需要研究反应堆项目,因为我有点难以理解反应式编程的工作原理。 block 方法在某些情况下会抛出错误。像这样订阅可以是一种替代方法,但您可能会在实际发送 webSocketMessage 之前返回您的 GameBean以上是关于WebSocketSession.send 不做任何事情的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV destroyWindow() 不做任何事情。
ListView onItemClickListener 不做任何事情