八、Web-WebSocket

  1. 之前我们已经了解了如何使用 Voovan 来开发一个提供 Http 服务端的方法.但是在现在 Web 开发中 WebSocket 逐渐也被广泛的使用,他的有状态连接和服务端推送的功能已经被广泛应用来支撑各种特殊场景.

那么 Voovan 也责无旁贷的提供了对 WebSocket 的支持.下面我们就来看看如何基于 Voovan 开发一个服务端的 Websocket.Voovan 采用异步的方式来管理 WebSocket, 使得他的开发同 Voovan 异步通信开发一脉相承并且极易上手.


Voovan 提供对 WebSocket 服务的支持.下面我们就简单的介绍一下: 首先通过 WebServer 类的 webSocket 方法即可简单的实现一个提供 WebSocket 的服务.同时基于 WebSocketRouter 类实现对onOpenonRecivedonSentonClose四个方法的支持。已达到提供服务的目的.


开发 WebSocket 首先我们要熟悉几个类:

  • WebServer 类: 该类的 Socket 方法提供给我们一个注册 WebSocket 服务的入口.
  • WebSocketRoute 类: 一个 WebSocket 业务处理类,Voovan 采用异步的方式调用这个类的各种事件.
  • WebSocketSession 类: 一个 WebSocket 会话类,提供了诸如:send,close,isConnect 等基于会话的方法.
  • WebSocketFilter 类: WebSocket 消息过滤器类

接下来我们来使用之前章节构造的 WebServer 实例, 来实现一个简单的 WebSocket 服务, 首先我们来看代码:

  1. webServer.socket("/websocket", new WebSocketRouter() {
  2. @Override
  3. public Object onOpen(WebSocketSession webSocketSession) {
  4. Logger.info("onOpen: WebSocket connect!");
  5. //调用发送函数发送
  6. try {
  7. webSocketSession.send("Send by persistent Object's send method in onOpen");
  8. webSocketSession.send("Send by send method in onOpen");
  9. } catch (SendMessageException e) {
  10. e.printStackTrace();
  11. }
  12. return "Server send: onOpen";
  13. }
  14. @Override
  15. public Object onRecived(WebSocketSession webSocketSession, Object obj) {
  16. String msg = (String)obj;
  17. Logger.info("onRecive: "+msg);
  18. msg = "This is server message. Client message: \r\n\t\""+msg+"\"";
  19. //调用发送函数发送
  20. try {
  21. webSocketSession.send("Send by send method in onRecive");
  22. } catch (SendMessageException e) {
  23. e.printStackTrace();
  24. }
  25. return msg;
  26. }
  27. @Override
  28. public void onSent(WebSocketSession webSocketSession, Object message) {
  29. Logger.info("----> onSend: " + message);
  30. }
  31. @Override
  32. public void onClose(WebSocketSession webSocketSession) {
  33. Logger.info("WebSocket close!");
  34. }
  35. }.addFilterChain(new StringFilter())); //使用字符串过滤器

首先我们来介绍一个WebServer.webSocket方法

  1. public void webSocket(String urlString, WebSocketRouter webSocketRouter) throws SendMessageException, ReadMessageException {
  • urlString: websocket 访问路由地址.
  • webSocketRouter: websocket 路由处理对象.通过查看例子可以发现要开发一个 WebSocket 类,首先我们要调用webSocket方法,并注册一个路由和 WebSocket 的路由处理类.

接下来我们介绍一下WebSocketRouter中的事件方法:

  • onOpen: 在 WebSocket 连接建立完成以后触发.
  • onRecive: 在 WebSocket 收到请求帧的时候触发.
  • onSent: 在 WebSocket 消息发送导Socket缓冲区后触发.
  • onClose: 在 WebSocket 关闭后触发.大家通过观察上面的代码可以和清楚的看到各个事件方法的使用.大家在开发过程中可以根据自己的业务需要来填充响应的代码至响应事件中即可完成.

过滤器

我们可以通过 WebSocketRouteraddFilterChain 方法为 WebSocketRouter 增加过滤器.上面的例子中我们增加了一个 StringFilter过滤器,这是一个字符串过滤器是一个继承于WebSocketFilter接口的类,他的作用是将 WebSocket 接收的 ByteBuffer 转换成 一个字符串对象供 WebSocketRouter 的 onRecived 调用. 这样这个过滤器类就可以被多个场景复用,且保证了WebSocketRouter的可单元测试的特性。下面我们来看一下 StringFilter 的实现:

  1. public class StringFilter implements WebSocketFilter {
  2. @Override
  3. public Object encode(WebSocketSession session, Object object) {
  4. if(object instanceof String){
  5. String sourceString = TObject.cast(object);
  6. return ByteBuffer.wrap(sourceString.getBytes());
  7. }
  8. return object;
  9. }
  10. @Override
  11. public Object decode(WebSocketSession session,Object object) {
  12. if(object instanceof ByteBuffer){
  13. return TByteBuffer.toString((ByteBuffer)object);
  14. }
  15. return object;
  16. }
  17. }

由于只有一个过滤器,我们可以发现一个规律, 所有过滤器链的第一个位置过滤器的 decode 方法接收到的都是 ByteBuffer对象,所有过滤器链最后一个位置的过滤器的 encode 方法都返回都是 ByteBuffer 对象,这一点大家在开发的时候需要注意.


如何接受和发送消息?

  • 如何接受消息:

onRecive 事件中的第二个参数 message 就是 WebSocket 从客户端接收到的数据.我们们可以在这里讲数据转换成需要个对象后进行处理.

  • 如何发送消息:

在 Voovan WebServer 中向客户端发送消息有三种方式:

  • onOpen 事件返回的数据将会被发送至客户端, 返回 null 时不发送任何消息.
  • onRecive 事件返回的数据将会被发送至客户端, 返回 null 时不发送任何消息.
  • 调用 WebSocketSession.send 来发送数据.也就是说,我们在 WebSocket 刚建立连接的时候就可以主动发送消息给客户端了,然后就是在收到消息后返回一个消息给客户端.接下来我们就可以通过 ws://127.0.0.1:28080/websocket来访问我们自己的 WebSocket 服务了.