diff --git a/src/com/wentch/redkale/net/http/WebSocket.java b/src/com/wentch/redkale/net/http/WebSocket.java index 9f64eb45c..9f2339691 100644 --- a/src/com/wentch/redkale/net/http/WebSocket.java +++ b/src/com/wentch/redkale/net/http/WebSocket.java @@ -12,6 +12,24 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** + * 一个WebSocket连接对应一个WebSocket实体,即一个WebSocket会绑定一个TCP连接。 + * WebSocket 有两种模式: + * 1) 普通模式: 协议上符合HTML5规范, 其流程顺序如下: + * 1.1 onOpen 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断登录态。 + * 1.2 createGroupid 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断用户权限是否符合。 + * 1.3 onConnected WebSocket成功连接后在准备接收数据前回调此方法。 + * 1.4 onMessage/onFragment+ WebSocket接收到消息后回调此消息类方法。 + * 1.5 onClose WebSocket被关闭后回调此方法。 + * + * 此模式下 以上方法都应该被重载。 + * + * 2) 原始二进制模式: 此模式有别于HTML5规范,可以视为原始的TCP连接。通常用于音频视频通讯场景。期流程顺序如下: + * 2.1 onOpen 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断登录态。 + * 2.2 createGroupid 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断用户权限是否符合。 + * 2.3 onRead WebSocket成功连接后回调此方法, 由此方法处理原始的TCP连接, 同时业务代码去控制WebSocket的关闭。 + * + * 此模式下 以上方法都应该被重载。 + *

* * @author zhangjx */ @@ -25,7 +43,7 @@ public abstract class WebSocket { WebSocketNodeService nodeService; - String sessionid; + Serializable sessionid; Serializable groupid; @@ -35,59 +53,149 @@ public abstract class WebSocket { } //---------------------------------------------------------------- + /** + * 发送消息体, 包含二进制/文本 + *

+ * @param packet + */ public final void send(WebSocketPacket packet) { if (this.runner != null) this.runner.sendMessage(packet); } + /** + * 显式地关闭WebSocket + */ public final void close() { if (this.runner != null) this.runner.closeRunner(); } + /** + * 发送单一的文本消息 + *

+ * @param text 不可为空 + */ public final void send(String text) { send(text, true); } + /** + * 发送文本消息 + *

+ * @param text 不可为空 + * @param last 是否最后一条 + */ public final void send(String text, boolean last) { send(new WebSocketPacket(text, last)); } + /** + * 发送单一的二进制消息 + *

+ * @param data + */ public final void send(byte[] data) { send(data, true); } + /** + * 发送二进制消息 + *

+ * @param data 不可为空 + * @param last 是否最后一条 + */ public final void send(byte[] data, boolean last) { send(new WebSocketPacket(data, last)); } //---------------------------------------------------------------- + /** + * 给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息 + *

+ * @param groupid + * @param text 不可为空 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendMessage(Serializable groupid, String text) { return sendMessage(groupid, text, true); } + /** + * 给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息 + *

+ * @param groupid + * @param data 不可为空 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendMessage(Serializable groupid, byte[] data) { return sendMessage(groupid, data, true); } + /** + * 给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息 + *

+ * @param groupid + * @param text 不可为空 + * @param last + * @return 为0表示成功, 其他值表示异常 + */ public final int sendMessage(Serializable groupid, String text, boolean last) { return sendMessage(groupid, false, text, last); } + /** + * 给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息 + *

+ * @param groupid + * @param data 不可为空 + * @param last 是否最后一条 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendMessage(Serializable groupid, byte[] data, boolean last) { return sendMessage(groupid, false, data, last); } + /** + * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送文本消息 + *

+ * @param groupid + * @param text 不可为空 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendRecentMessage(Serializable groupid, String text) { return sendRecentMessage(groupid, text, true); } + /** + * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送二进制消息 + *

+ * @param groupid + * @param data 不可为空 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendRecentMessage(Serializable groupid, byte[] data) { return sendRecentMessage(groupid, data, true); } + /** + * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送文本消息 + *

+ * @param groupid + * @param text 不可为空 + * @param last 是否最后一条 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendRecentMessage(Serializable groupid, String text, boolean last) { return sendMessage(groupid, true, text, last); } + /** + * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送二进制消息 + *

+ * @param groupid + * @param data 不可为空 + * @param last 是否最后一条 + * @return 为0表示成功, 其他值表示异常 + */ public final int sendRecentMessage(Serializable groupid, byte[] data, boolean last) { return sendMessage(groupid, true, data, last); } @@ -110,32 +218,73 @@ public abstract class WebSocket { } } + /** + * 获取当前WebSocket下的属性 + *

+ * @param + * @param name + * @return + */ @SuppressWarnings("unchecked") public final T getAttribute(String name) { return (T) attributes.get(name); } - public final void removeAttribute(String name) { - attributes.remove(name); + /** + * 移出当前WebSocket下的属性 + *

+ * @param + * @param name + * @return + */ + public final T removeAttribute(String name) { + return (T) attributes.remove(name); } + /** + * 给当前WebSocket下的增加属性 + *

+ * @param name + * @param value + */ public final void setAttribute(String name, Object value) { attributes.put(name, value); } + /** + * 获取当前WebSocket所属的groupid + *

+ * @return + */ public final Serializable getGroupid() { return groupid; } - public final String getSessionid() { + /** + * 获取当前WebSocket的会话ID, 不会为null + *

+ * @return + */ + public final Serializable getSessionid() { return sessionid; } //------------------------------------------------------------------- + /** + * 获取当前WebSocket所属的WebSocketGroup, 不会为null + *

+ * @return + */ protected final WebSocketGroup getWebSocketGroup() { return group; } + /** + * 获取指定groupid的WebSocketGroup, 没有返回null + *

+ * @param groupid + * @return + */ protected final WebSocketGroup getWebSocketGroup(long groupid) { return engine.getWebSocketGroup(groupid); } @@ -151,12 +300,12 @@ public abstract class WebSocket { * @param request * @return */ - public String onOpen(final HttpRequest request) { + public Serializable onOpen(final HttpRequest request) { return request.getSessionid(false); } /** - * 返回GroupID, null表示异常 + * 创建groupid, null表示异常 * * @return */ @@ -165,13 +314,8 @@ public abstract class WebSocket { } /** - * WebSocketBinary模式流程顺序: onOpen、createGroupid、onRead - * WebSocket流程顺序: onOpen、createGroupid、onConnected、onMessage/onFragment+、onClose - */ - - /** - * - * @param channel + * + * @param channel */ public void onRead(AsyncConnection channel) { } diff --git a/src/com/wentch/redkale/net/http/WebSocketServlet.java b/src/com/wentch/redkale/net/http/WebSocketServlet.java index 0d3bad220..7725e1d8f 100644 --- a/src/com/wentch/redkale/net/http/WebSocketServlet.java +++ b/src/com/wentch/redkale/net/http/WebSocketServlet.java @@ -17,6 +17,19 @@ import java.util.logging.*; import javax.annotation.*; /** + * 当WebSocketServlet接收一个TCP连接后,进行协议判断,如果成功就会创建一个WebSocket。 + * + * WebSocketServlet + * | + * | + * WebSocketEngine + * / \ + * / \ + * / \ + * WebSocketGroup1 WebSocketGroup2 + * / \ / \ + * / \ / \ + * WebSocket1 WebSocket2 WebSocket3 WebSocket4 * * @author zhangjx */ @@ -75,7 +88,7 @@ public abstract class WebSocketServlet extends HttpServlet { final WebSocket webSocket = this.createWebSocket(); webSocket.engine = engine; webSocket.nodeService = nodeService; - String sessionid = webSocket.onOpen(request); + Serializable sessionid = webSocket.onOpen(request); if (sessionid == null) { if (debug) logger.finer("WebSocket connect abort, Not found sessionid. request=" + request); response.finish(true);