From 43d5f5a48c5b3a94b59a1ff1b91dcfa6e0a1b47c Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Mon, 29 May 2017 17:21:34 +0800 Subject: [PATCH] --- net.html | 305 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 157 insertions(+), 148 deletions(-) diff --git a/net.html b/net.html index d7cc2a25c..450d9505d 100644 --- a/net.html +++ b/net.html @@ -105,7 +105,7 @@
继承HttpServlet的子类可以使用其自带的鉴权、请求分支、缓存等功能, 一个典型的操作用户HttpServlet:
-@WebServlet(value = {"/user/*"}, comment = "用户模块服务") //拦截所有 /user/ 开头的请求
+ @WebServlet(value = {"/user/*"}, comment = "用户模块服务") //拦截所有 /user/ 开头的请求
public class UserServlet extends BaseSerlvet {
@Resource
@@ -114,50 +114,51 @@
//登录操作
//因为HttpMapping的判断规则用的是String.startsWith,所以HttpMapping.url不能用正则表达式,只能是getRequestURI的前缀
//且同一个HttpServlet类内的所有HttpMapping不能存在包含关系, 如 /user/myinfo 和 /user/myinforecord 不能存在同一HttpServlet中。
- @HttpMapping(url = "/user/login", comment = "用户登录")
- @HttpParam(name = "bean", type = LoginBean.class, comment = "登录参数对象")
+ @HttpMapping(url = "/user/login", auth = false, comment = "用户登录")
+ @HttpParam(name = "bean", type = LoginBean.class, comment = "登录参数对象")
public void login(HttpRequest req, HttpResponse resp) throws IOException {
- LoginBean bean = req.getJsonParameter(LoginBean.class, "bean"); //获取参数
+ LoginBean bean = req.getJsonParameter(LoginBean.class, "bean"); //获取参数
RetResult<UserInfo> result = service.login(bean); //登录操作, service内部判断bean的合法性
resp.finishJson(result); //输出结果
}
//获取当前用户信息
//未登录的请求会被BaseSerlvet.authenticate方法拦截,因此能进入该方法说明用户态存在
- @HttpMapping(url = "/user/myinfo", comment = "获取当前用户信息")
+ @HttpMapping(url = "/user/myinfo", comment = "获取当前用户信息")
public void myinfo(HttpRequest req, HttpResponse resp) throws IOException {
UserInfo user = service.current(req.getSessionid(false));
- //或者使用 user = req.getAttribute("_current_userinfo"); 因为BaseSerlvet.authenticate方法已经将UserInfo注入到_current_userinfo属性中
+ //或者使用 user = req.getAttribute("_current_userinfo"); 因为BaseSerlvet.authenticate方法已经将UserInfo注入到_current_userinfo属性中
resp.finishJson(user); //输出用户信息
}
//获取指定用户ID的用户信息, 请求如: /user/username/43565443
// 翻页查询想缓存就需要将翻页信息带进url: /user/query/page:2/size:50 。
- @HttpMapping(url = "/user/userinfo/", comment = "获取指定用户ID的用户信息")
- @HttpParam(name = "#", type = int.class, comment = "用户ID")
+ @HttpMapping(url = "/user/userinfo/", comment = "获取指定用户ID的用户信息")
+ @HttpParam(name = "#", type = int.class, comment = "用户ID")
public void userinfo(HttpRequest req, HttpResponse resp) throws IOException {
UserInfo user = service.findUserInfo(Integer.parseInt(req.getRequstURILastPath()));
resp.finishJson(user); //输出用户信息
}
//更新个人头像
- @HttpMapping(url = "/user/updateface", comment = "更新用户头像")
+ @HttpMapping(url = "/user/updateface", comment = "更新用户头像")
public void updateface(HttpRequest req, HttpResponse resp) throws IOException {
UserInfo user = service.current(req.getSessionid(false));
for (MultiPart part : req.multiParts()) { //遍历上传文件列表
byte[] byts = part.getContentBytes(5 * 1024 * 1024L); //图片大小不能超过5M,超过5M返回null
if (byts == null) {
- resp.finishJson(new RetResult(102, "上传的文件过大"));
+ resp.finishJson(new RetResult(102, "上传的文件过大"));
} else {
- BufferedImage img = ImageIO.read(new ByteArrayInputStream(byts));
+ BufferedImage img = ImageIO.read(new ByteArrayInputStream(byts));
//... 此处处理并存储头像图片
resp.finishJson(RetResult.SUCCESS); //输出成功信息
}
return; //头像图片仅会传一个, 只需要读取一个即可返回
}
- resp.finishJson(new RetResult(103, "没有上传图片"));
+ resp.finishJson(new RetResult(103, "没有上传图片"));
}
-}
+}
+ 如上,所有/user/前缀的请求都会进入UserServlet,若没匹配的则返回505错误,为了方便以后编写前方静动分离服务器转发规则,比较好的习惯是将项目中所有动态Servlet加一个固定前缀,在 application.xml 里设置path即可。
<server protocol="HTTP" port="6060" root="root">
<services autoload="true" />
@@ -176,7 +177,7 @@
一个WebSocket连接对应一个WebSocket实体,即一个WebSocket会绑定一个TCP连接。且有两种模式:
1) 普通模式: 协议上符合HTML5规范, 其流程顺序如下:
1.1 onOpen 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断登录态。
- 1.2 createGroupid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。
+ 1.2 createUserid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。
1.3 onConnected WebSocket成功连接后在准备接收数据前回调此方法。
1.4 onMessage/onFragment+ WebSocket接收到消息后回调此消息类方法。
1.5 onClose WebSocket被关闭后回调此方法。
@@ -184,56 +185,51 @@
2) 原始二进制模式: 此模式有别于HTML5规范,可以视为原始的TCP连接。通常用于音频视频通讯场景。其流程顺序如下:
2.1 onOpen 如果方法返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断登录态。
- 2.2 createGroupid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。
+ 2.2 createUserid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。
2.3 onRead WebSocket成功连接后回调此方法, 由此方法处理原始的TCP连接, 同时业务代码去控制WebSocket的关闭。
此模式下 以上方法都应该被重载。
实现一个WebSocket服务需要继承 org.redkale.net.http.WebSocketServlet,以下是一个简单的聊天范例:
- @WebServlet("/ws/chat")
+ @WebServlet("/ws/chat")
public class ChatWebSocketServlet extends WebSocketServlet {
- @Resource //[Redkale内置资源]
- protected JsonConvert jsonConvert;
-
@Resource
private UserService userService;
@Override
public void init(HttpContext context, AnyValue conf) {
- System.out.println("本实例的WebSocketEngine: " + super.engine);
- System.out.println("本实例的WebSocketNode: " + super.node);
+ System.out.println("本实例的WebSocketNode: " + super.node);
}
@Override
public void destroy(HttpContext context, AnyValue conf) {
- System.out.println("关闭了ChatWebSocketServlet");
+ System.out.println("关闭了ChatWebSocketServlet");
}
@Override
- protected WebSocket createWebSocket() {
+ protected WebSocket<Integer, ChatMessage> createWebSocket() {
- return new WebSocket() {
+ return new WebSocket<Integer, ChatMessage>() {
private UserInfo user;
@Override
- public void onMessage(String text) { // text 接收的格式: {"receiveid":200000001, "content":"Hi Redkale!"}
- final ChatMessage message = jsonConvert.convertFrom(ChatMessage.class, text); //获取给对方的消息体信息
+ public void onMessage(ChatMessage message, boolean last) { // text 接收的格式: {"receiveid":200000001, "content":"Hi Redkale!"}
message.sendid = user.getUserid(); //将当前用户设为消息的发送方
message.sendtime = System.currentTimeMillis(); //设置消息发送时间
//给接收方发送消息, 即使接收方在其他WebSocket进程节点上有链接,Redkale也会自动发送到其他链接进程节点上。
- super.sendEachMessage(message.receiveid, jsonConvert.convertTo(message));
+ super.sendMessage(message, message.receiveid);
}
@Override
- protected Serializable createGroupid() { //以用户ID作为WebSocketGroup的groupid
+ protected CompletableFuture<Integer> createUserid() { //创建用户ID
this.user = userService.current(String.valueOf(super.getSessionid()));
- return this.user == null ? null : this.user.getUserid();
+ return CompletableFuture.completedFuture(this.user == null ? null : this.user.getUserid());
}
@Override
- public Serializable onOpen(HttpRequest request) {
- return request.getSessionid(false); //以request中的sessionid字符串作为WebSocket的sessionid
+ public CompletableFuture<String> onOpen(HttpRequest request) {
+ return CompletableFuture.completedFuture(request.getSessionid(false)); //以request中的sessionid字符串作为WebSocket的sessionid
}
};
@@ -249,7 +245,8 @@
public long sendtime; //消息发送时间
}
-}
+}
+
. HttpRequest 对象
public class HttpRequest {
@@ -268,14 +265,29 @@
public String getBodyUTF8();
//获取请求内容的byte[]
- public byte[] getBody();
+ public byte[] getBody();
+
+ //获取请求内容的JavaBean对象
+ public <T> T getBodyJson(java.lang.reflect.Type type);
+ //获取请求内容的JavaBean对象
+ public <T> T getBodyJson(JsonConvert convert, java.lang.reflect.Type type);
+
//获取文件上传对象
public MultiContext getMultiContext();
//获取文件上传信息列表 等价于 getMultiContext().parts();
public Iterable<MultiPart> multiParts() throws IOException;
+ //获取当前用户信息 数据类型由@HttpUserType指定
+ public <T> T currentUser();
+
+ //获取模块ID,来自@HttpServlet.moduleid()
+ public int getModuleid();
+
+ //获取操作ID,来自@HttpMapping.actionid()
+ public int getActionid();
+
//获取sessionid
public String getSessionid(boolean autoCreate);
@@ -361,54 +373,54 @@
// 获取type参数: double type = request.getRequstURILastPath(0.0); //type = 2.0
public double getRequstURILastPath(double defvalue);
- //从prefix之后截取getRequestURI再对"/"进行分隔
+ //从prefix之后截取getRequestURI再对"/"进行分隔
public String[] getRequstURIPaths(String prefix);
// 获取请求URL分段中含prefix段的值
// 例如请求URL /pipes/record/query/name:hello
- // 获取name参数: String name = request.getRequstURIPath("name:", "none");
+ // 获取name参数: String name = request.getRequstURIPath("name:", "none");
public String getRequstURIPath(String prefix, String defaultValue);
// 获取请求URL分段中含prefix段的short值
// 例如请求URL /pipes/record/query/type:10
- // 获取type参数: short type = request.getRequstURIPath("type:", (short)0);
+ // 获取type参数: short type = request.getRequstURIPath("type:", (short)0);
public short getRequstURIPath(String prefix, short defaultValue);
// 获取请求URL分段中含prefix段的short值
// 例如请求URL /pipes/record/query/type:a
- // 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); type = 10
+ // 获取type参数: short type = request.getRequstURIPath(16, "type:", (short)0); type = 10
public short getRequstURIPath(int radix, String prefix, short defvalue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:50
- // 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
- // 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
+ // 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
+ // 获取limit参数: int limit = request.getRequstURIPath("limit:", 20);
public int getRequstURIPath(String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的int值
// 例如请求URL /pipes/record/query/offset:2/limit:10
- // 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
- // 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
+ // 获取offset参数: int offset = request.getRequstURIPath("offset:", 1);
+ // 获取limit参数: int limit = request.getRequstURIPath(16, "limit:", 20); // limit = 16
public int getRequstURIPath(int radix, String prefix, int defaultValue);
// 获取请求URL分段中含prefix段的float值
// 例如请求URL /pipes/record/query/point:40.0
- // 获取time参数: float point = request.getRequstURIPath("point:", 0.0f);
+ // 获取time参数: float point = request.getRequstURIPath("point:", 0.0f);
public float getRequstURIPath(String prefix, float defvalue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
- // 获取time参数: long time = request.getRequstURIPath("time:", 0L);
+ // 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(String prefix, long defaultValue);
// 获取请求URL分段中含prefix段的long值
// 例如请求URL /pipes/record/query/time:1453104341363/id:40
- // 获取time参数: long time = request.getRequstURIPath("time:", 0L);
+ // 获取time参数: long time = request.getRequstURIPath("time:", 0L);
public long getRequstURIPath(int radix, String prefix, long defvalue);
// 获取请求URL分段中含prefix段的double值 <br>
// 例如请求URL /pipes/record/query/point:40.0 <br>
- // 获取time参数: double point = request.getRequstURIPath("point:", 0.0);
+ // 获取time参数: double point = request.getRequstURIPath("point:", 0.0);
public double getRequstURIPath(String prefix, double defvalue);
//获取所有的header名
@@ -504,20 +516,20 @@
//获取指定的参数double值, 没有返回默认double值
public double getDoubleParameter(String name, double defaultValue);
- //获取翻页对象 同 getFlipper("flipper", false, 0);
+ //获取翻页对象 同 getFlipper("flipper", false, 0);
public org.redkale.source.Flipper getFlipper();
- //获取翻页对象 同 getFlipper("flipper", needcreate, 0);
+ //获取翻页对象 同 getFlipper("flipper", needcreate, 0);
public org.redkale.source.Flipper getFlipper(boolean needcreate);
- //获取翻页对象 同 getFlipper("flipper", false, maxLimit);
+ //获取翻页对象 同 getFlipper("flipper", false, maxLimit);
public org.redkale.source.Flipper getFlipper(int maxLimit);
- //获取翻页对象 同 getFlipper("flipper", needcreate, maxLimit)
+ //获取翻页对象 同 getFlipper("flipper", needcreate, maxLimit)
public org.redkale.source.Flipper getFlipper(boolean needcreate, int maxLimit);
//获取翻页对象 http://redkale.org/pipes/records/list/offset:0/limit:20/sort:createtime%20ASC
- //http://redkale.org/pipes/records/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
+ //http://redkale.org/pipes/records/list?flipper={'offset':0,'limit':20, 'sort':'createtime ASC'}
//以上两种接口都可以获取到翻页对象
public org.redkale.source.Flipper getFlipper(String name, boolean needcreate, int maxLimit);
@@ -527,13 +539,13 @@
//获取所有属性值, servlet执行完后会被清空
public Map<String, Object> getAttributes();
- //获取指定属性值
+ //获取指定属性值, servlet执行完后会被清空
public <T> T getAttribute(String name);
//删除指定属性
public void removeAttribute(String name);
- //设置属性值
+ //设置属性值, servlet执行完后会被清空
public void setAttribute(String name, Object value);
//获取request创建时间
@@ -551,6 +563,12 @@
//增加Cookie值
public HttpResponse addCookie(Collection<HttpCookie> cookies);
+ //创建AsyncHandler实例,将非字符串对象以JSON格式输出,字符串以文本输出
+ public AsyncHandler createAsyncHandler();
+
+ //传入的AsyncHandler子类必须是public,且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数
+ public <H extends AsyncHandler> H createAsyncHandler(Class<H> handlerClass);
+
//设置状态码
public void setStatus(int status);
@@ -585,9 +603,9 @@
//异步输出指定内容
public <A> void sendBody(ByteBuffer buffer, A attachment, AsyncHandler<Integer, A> handler);
- //创建AsyncHandler实例,将非字符串对象以JSON格式输出,字符串以文本输出
- public AsyncHandler createAsyncHandler();
-
+ //异步输出指定内容
+ public <A> void sendBody(ByteBuffer[] buffers, A attachment, AsyncHandler<Integer, A> handler);
+
//关闭HTTP连接,如果是keep-alive则不强制关闭
public void finish();
@@ -616,14 +634,20 @@
public void finishJson(final JsonConvert convert, final org.redkale.service.RetResult ret);
//将CompletableFuture的结果对象以JSON格式输出
- public void finishJson(CompletableFuture future);
+ public void finishJson(final CompletableFuture future);
//将CompletableFuture的结果对象以JSON格式输出
- public void finishJson(JsonConvert convert, CompletableFuture future);
+ public void finishJson(final JsonConvert convert, final CompletableFuture future);
//将CompletableFuture的结果对象以JSON格式输出
public void finishJson(final JsonConvert convert, final Type type, final CompletableFuture future);
+ //将HttpResult的结果对象以JSON格式输出
+ public void finishJson(final HttpResult result);
+
+ //将HttpResult的结果对象以JSON格式输出
+ public void finishJson(final JsonConvert convert, final HttpResult result) ;
+
//将指定字符串以响应结果输出
public void finish(String obj);
@@ -660,76 +684,106 @@
public void finish(final String filename, File file) throws IOException;
//HttpResponse回收时回调的监听方法
- public void setRecycleListener(BiConsumer<HttpRequest, HttpResponse> recycleListener);
+ public void recycleListener(BiConsumer<HttpRequest, HttpResponse> recycleListener);
+
}
. WebSocket 对象
- public abstract class WebSocket {
+ public abstract class WebSocket<G, T> {
- //发送消息体, 包含二进制/文本 返回结果0表示成功,非0表示错误码
- public int send(WebSocketPacket packet);
+ //给自身发送消息, 消息类型是String或byte[]或可JavaBean对象 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> send(Object message);
- //发送单一的文本消息 返回结果0表示成功,非0表示错误码
- public int send(String text);
+ //给自身发送消息, 消息类型是String或byte[]或可JavaBean对象 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> send(Object message, boolean last);
- //发送文本消息 返回结果0表示成功,非0表示错误码
- public int send(String text, boolean last);
+ //给自身发送消息, 消息类型是JavaBean对象 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> send(JsonConvert convert, Object message);
- //发送单一的二进制消息 返回结果0表示成功,非0表示错误码
- public int send(byte[] data);
+ //给自身发送消息, 消息类型是JavaBean对象 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> send(JsonConvert convert, Object message, boolean last);
- //发送单一的二进制消息 返回结果0表示成功,非0表示错误码
- public int send(byte[] data, boolean last);
+ //给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> sendMessage(Object message, G... userids);
- //发送消息, 消息类型是String或byte[] 返回结果0表示成功,非0表示错误码
- public int send(Serializable message, boolean last);
+ //给指定userid的WebSocket节点发送 二进制消息/文本消息/JavaBean对象消息 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> sendMessage(Object message, boolean last, G... userids);
- //给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息
- public int sendEachMessage(Serializable groupid, String text);
+ //给所有人广播消息, 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> broadcastMessage(final Object message);
- //给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息
- public int sendEachMessage(Serializable groupid, String text, boolean last);
+ //给所有人广播消息, 返回结果0表示成功,非0表示错误码
+ public CompletableFuture<Integer> broadcastMessage(final Object message, boolean last);
- //给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息
- public int sendEachMessage(Serializable groupid, byte[] data);
+ //获取用户在线的SNCP节点地址列表,不是分布式则返回元素数量为1,且元素值为null的列表
+ public CompletableFuture<Collection<InetSocketAddress>> getRpcNodeAddresses(final Serializable userid);
- //给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息
- public int sendEachMessage(Serializable groupid, byte[] data, boolean last);
-
- //给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息
- public int sendRecentMessage(Serializable groupid, String text);
-
- //给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息
- public int sendRecentMessage(Serializable groupid, String text, boolean last);
-
- //给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送二进制消息
- public int sendRecentMessage(Serializable groupid, byte[] data);
-
- //给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送二进制消息
- public int sendRecentMessage(Serializable groupid, byte[] data, boolean last);
+ //获取在线用户的详细连接信息
+ public CompletableFuture<Map<InetSocketAddress, List<String>>> getRpcNodeWebSocketAddresses(final Serializable userid);
//发送PING消息 返回结果0表示成功,非0表示错误码
- public int sendPing();
+ public CompletableFuture<Integer> sendPing();
//发送PING消息,附带其他信息 返回结果0表示成功,非0表示错误码
- public int sendPing(byte[] data);
+ public CompletableFuture<Integer> sendPing(byte[] data);
//发送PONG消息,附带其他信息 返回结果0表示成功,非0表示错误码
- public int sendPong(byte[] data);
+ public CompletableFuture<Integer> sendPong(byte[] data);
+
+
+ //获取指定userid的WebSocket数组, 没有返回null 此方法用于单用户多连接模式
+ protected Stream<WebSocket> getLocalWebSockets(G userid);
+
+
+ //获取指定userid的WebSocket数组, 没有返回null 此方法用于单用户单连接模式
+ protected WebSocket findLocalWebSocket(G userid);
+
+
+ //获取当前进程节点所有在线的WebSocket
+ protected Collection<WebSocket> getLocalWebSockets();
+
+
+ //返回sessionid, null表示连接不合法或异常,默认实现是request.sessionid(true),通常需要重写该方法
+ protected CompletableFuture<String> onOpen(final HttpRequest request);
+
+
+ //创建userid, null表示异常, 必须实现该方法
+ protected abstract G createUserid();
+
+ //标记为@WebSocketBinary才需要重写此方法
+ public void onRead(AsyncConnection channel);
+
+ //WebSokcet连接成功后的回调方法
+ public void onConnected();
+
+ //ping后的回调方法
+ public void onPing(byte[] bytes);
+
+ //pong后的回调方法
+ public void onPong(byte[] bytes);
+
+ //接收到消息的回调方法
+ public void onMessage(T message, boolean last);
+
+ //接收到二进制消息的回调方法
+ public void onMessage(byte[] bytes, boolean last);
+
+ //关闭的回调方法,调用此方法时WebSocket已经被关闭
+ public void onClose(int code, String reason);
//获取当前WebSocket下的属性
- public <T> T getAttribute(String name);
+ public T getAttribute(String name);
//移出当前WebSocket下的属性
- public <T> T removeAttribute(String name);
+ public T removeAttribute(String name);
//给当前WebSocket下的增加属性
public void setAttribute(String name, Object value);
- //获取当前WebSocket所属的groupid
- public Serializable getGroupid();
+ //获取当前WebSocket所属的userid
+ public G userid();
//获取当前WebSocket的会话ID, 不会为null
public Serializable getSessionid();
@@ -743,58 +797,13 @@
//获取WebSocket创建时间
public long getCreatetime();
+ //获取最后一次发送消息的时间
+ public long getLastSendTime();
+
//显式地关闭WebSocket
public void close();
-
- //获取当前WebSocket所属的WebSocketGroup, 不会为null
- protected WebSocketGroup getWebSocketGroup();
-
- //获取指定groupid的WebSocketGroup, 没有返回null
- protected WebSocketGroup getWebSocketGroup(Serializable groupid);
-
- //获取当前进程节点所有在线的WebSocketGroup
- protected Collection<WebSocketGroup> getWebSocketGroups();
-
- //获取在线用户的节点地址列表
- protected Collection<InetSocketAddress> getOnlineNodes(Serializable groupid);
-
- //获取在线用户的详细连接信息
- protected Map<InetSocketAddress, List<String>> getOnlineRemoteAddress(Serializable groupid);
-
- //返回sessionid, null表示连接不合法或异常,默认实现是request.getSessionid(false),通常需要重写该方法
- public Serializable onOpen(final HttpRequest request);
-
- //创建groupid, null表示异常, 必须实现该方法, 通常为用户ID为groupid
- protected abstract Serializable createGroupid();
-
- //标记为@WebSocketBinary才需要重写此方法
- public void onRead(AsyncConnection channel) {
- }
-
- public void onConnected() {
- }
-
- public void onMessage(String text) {
- }
-
- public void onPing(byte[] bytes) {
- }
-
- public void onPong(byte[] bytes) {
- }
-
- public void onMessage(byte[] bytes) {
- }
-
- public void onFragment(String text, boolean last) {
- }
-
- public void onFragment(byte[] bytes, boolean last) {
- }
-
- public void onClose(int code, String reason) {
- }
-}
+}
+
SNCP 协议