Websocket服务器:每个会话处理关闭事件
Posted
技术标签:
【中文标题】Websocket服务器:每个会话处理关闭事件【英文标题】:Websocket server: Handle close event per session 【发布时间】:2017-09-21 10:09:31 【问题描述】:有没有办法处理每个会话的 websocket 的服务器端关闭事件?这就是我目前的实现方式:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint
@OnOpen
public void onOpen(Session session)
System.out.println("Websocket opened");
CustomWebsocketHandler handler = new CustomWebsocketHandler(session); // see below
// ...
@OnClose
public void onClose(Session session, CloseReason reason)
System.out.println("Websocket closed. Reason: " + reason);
但我想将新的 Session
实例包装在自定义对象中。对于消息,我可以通过addMessageHandler
将处理程序直接添加到特定会话中。但是如何在该特定会话上为 onClose
事件添加处理程序?:
class CustomWebsocketHandler
public CustomWebsocketHandler(Session session)
session.addMessageHandler((MessageHandler.Whole<String>) this::handleMessage);
// How to hook up close event to handleClose()?
private void handleMessage(String message) /* ... */
private void handleClose() /* ... */
我的一个想法是跟踪WebsocketServerEndpoint
和它们各自的CustomWebsocketHandler
实例中的每个会话,并为每个关闭事件遍历它们,转发事件。然而这非常麻烦并且容易出错:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint
private List<Pair<Session, CustomWebsocketHandler>> sessions = new ArrayList<>();
@OnOpen
public void onOpen(Session session)
// ...
sessions.add(Pair.of(session, handler)); // not hashable I suppose
@OnClose
public void onClose(Session session, CloseReason reason)
// ...
for (Iterator<Pair<Session, CustomWebsocketHandler>> it = sessions.iterator(); it.hasNext(); )
Pair<Session, CustomWebsocketHandler> pair = it.next();
if (pair.getLeft() == session)
pair.getRight().handleClose();
it.remove();
break;
在客户端这很容易,因为每个连接都可以使用自己的 ClientEndpoint
-annotated 类实例:
webSocketContainer.connectToServer(endpointInstance, websocketURI);
服务器端是否存在类似的东西,或者是否可以干净地处理每个会话的服务器端onClose
(最终还有onError
)事件?
【问题讨论】:
【参考方案1】:默认情况下,会为每个新客户端创建一个 ServerEndpoint
-annotated 类的新实例。此行为由ServerEndpointConfig.Configurator#getEndpointInstance
方法控制:
此方法的平台默认实现每次调用都会返回一个新的端点实例,从而确保每个客户端都有一个端点实例,即默认部署基数。
这意味着在 WebsocketServerEndpoint
类本身中存储特定于会话的状态是安全的,而无需手动将会话与自定义连接实例相关联:
@ServerEndpoint("/ws")
public class WebsocketServerEndpoint
private CustomWebsocketHandler handler;
@OnOpen
public void onOpen(Session session)
handler = new CustomWebsocketHandler(session);
@OnClose
public void onClose(Session session, CloseReason reason)
handler.handleClose();
此时,将带注释的类 WebsocketServerEndpoint
设置为 CustomWebsocketHandler
本身可能更容易,因为它具有相同的语义:每个连接一个实例并处理 websocket 事件。
【讨论】:
以上是关于Websocket服务器:每个会话处理关闭事件的主要内容,如果未能解决你的问题,请参考以下文章
为多个主机上的 PHP 站点处理会话的最佳方法是啥? [关闭]
关闭连接到 Mojo websocket 的 Mojo::IOLoop 重复事件