如何将数据附加到套接字连接以便在 `SessionDisconnectEvent` 上获取此数据?

Posted

技术标签:

【中文标题】如何将数据附加到套接字连接以便在 `SessionDisconnectEvent` 上获取此数据?【英文标题】:How to attach data to socket connection in order to get this data on `SessionDisconnectEvent`? 【发布时间】:2019-09-16 08:09:50 【问题描述】:

我想要达到的目标

当套接字在服务器端使用@EventListener 断开连接时,我想获取我用作@DestinationVariable 的字符串变量,称为lobbyName

@Component
public class WebSocketEventListener 

    private SimpMessageSendingOperations messagingTemplate;

    public WebSocketEventListener(SimpMessageSendingOperations messagingTemplate) 
        this.messagingTemplate = messagingTemplate;
    

    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) 
        //here I want to get my data
    

我的问题

我一直在尝试使用SessionDisonnectEvent 获取lobbyName,但我不知道如何、何时以及在何处放置此lobbyName 以便将其放入SessionDisconnectEvent

我一直在尝试的事情

在服务器端:

@Controller
public class WebSocketController 

    private final SimpMessagingTemplate template;

    WebSocketController(SimpMessagingTemplate template) 
        this.template = template;
    

    public void pokeLobby(@DestinationVariable String lobbyName, SocketMessage message) 
//        This didn't work 
//        Map<String, Object> headers = new HashMap<>();
//        headers.put("lobbyName", lobbyName);
//        this.template.convertAndSend("/lobby/"+lobbyName.toLowerCase(), message, headers);
        this.template.convertAndSend("/lobby/"+lobbyName.toLowerCase(), message);
    

可以在客户端做吗? :

  connectToLobbyWebSocket(lobbyName: string): void 
    const ws = new SockJS(this.addressStorage.apiAddress + '/socket');
    this.stompClient = Stomp.over(ws);
    // this.stompClient.debug = null;
    const that = this;
    this.stompClient.connect(, function () 
      that.stompClient.subscribe('/lobby/' + lobbyName, (message) => 
        if (message.body) 
          that.socketMessage.next(message.body); //client logic
        
      );
    );
  

编辑(进度)

由于我可以在SessionDisconnectEvent 上轻松获得sessionId,因此我决定将sessionId(握手时)更改为playerId:lobbyName:uuid 我对这个解决方案不太满意,所以如果您有任何建议,我会全力以赴。

const ws = new SockJS(this.addressStorage.apiAddress + '/socket', null, 
  sessionId: function (): string 
    return that.authManager.playerId + ':' + lobbyName + ':' + uuid();
  
);

【问题讨论】:

【参考方案1】:

您可以在消息正文中将 lobbyName 作为属性发送,并像这样在侦听器中获取它:

@EventListener
public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) 
    StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
    String lobbyName = (String) headerAccessor.getSessionAttributes().get("lobbyName");
    if(lobbyName != null) 
        SocketMessage message = new SocketMessage();
        messagingTemplate.convertAndSend("/topic/public/"+lobbyName, message);
    

【讨论】:

以上是关于如何将数据附加到套接字连接以便在 `SessionDisconnectEvent` 上获取此数据?的主要内容,如果未能解决你的问题,请参考以下文章

golang 将套接字附加到标准输入/标准输出

Java:绑定和连接方法

php+mysql,将用户session信息存到数据库,如何及时删掉登陆超时的用户信息呢?

如何使用nodejs在对话流履行中将数据附加到firebase?

如何同时支持 IPv4 和 IPv6 连接

如何将数据库附加到 Heroku 中的应用程序?