过去都是使用浏览器端插件(如flash和java applet)与服务器建立套接字通信,这些插件技术曾经广泛应用在网页聊天和网页游戏,html5提供的websocket有取代这些插件的趋势。

在websocket之前,实现服务器向浏览器推送消息有两种方式:ajax轮询和comet长轮询。

  • ajax轮询(polling):浏览器端不停地向服务器发起请求,问:“有新数据没有?”,不管有没有数据它都会返回来。这种方式不管对客户端还是对服务器都是巨大的压力。
  • comet技术(long-polling):浏览器发起一次请求,与服务器建立一个长连接,直到数据来临时才回复浏览器。一个请求结束之后,浏览器会马上发起另一个请求。这种技术的缺点是需要服务器维护的请求数很多。相当于有很多请求在同时发生。这种技术依旧流行。

一、Java中的websocket库

websocket是java标准库的一部分,位于javax包下,但它只是定义一些接口。
websocket有不同的实现,如Tomcat的,jetty的,Spring的,还有一个名叫TooTallNate组织发布的java-websocket库,atmosphere库,socket.io的java版本等。

  • socket.io:https://github.com/socketio/socket.io-client-java,这个库只是一个client,并没有提供server实现。
  • ToolTallNate库官方网址:http://java-websocket.org/,这个库号称是barebone(皮包骨,意思是非常紧凑精简)的。它的宣传口号是:A barebones WebSocket client and server implementation written in 100% Java.
  • Atmosphere: The Asynchronous WebSocket/Comet Framework.Atmosphere transparently supports WebSockets, Server Sent Events (SSE), Long-Polling, HTTP Streaming (Forever frame) and JSONP.

二、Python中的websocket库

websocket协议本身并不复杂,100行Python代码可以实现简单的websocket协议。
Python中最基础的websocket库是gevent.websocket。使用Flask的人们对这个库进行了一下封装,让它变得更好用,这个库名叫flask-sockets。
还有一个封装得比较重的库flask-socketio。
但是我运行flask-socketio和flask-sockets这两个库都失败了,gevent-websocket运行成功了。

在JS中有一个库socketio,这个库能够兼容各个版本的浏览器,是对websocket的封装,在网页端用这个库应该是最佳选择。

三、旧版的tomcat的websocket

在javax.websocket接口出来之前,tomcat7就已经对websocket提供支持了。于是在javax.websocket出来之后,tomcat8就开始废弃tomcat7中定义的websocket,tomcat7关于websocket的包位于org.apache.catalina.websocket中。

包org.apache.catalina.websocket中的这些类为WebSocket开发服务端提供了支持,这些类的主要功能简述如下:

1、Constants:包org.apache.catalina.websocket中用到的常数定义在这个类中,它只包含静态常数定义,无任何逻辑实现。
2、MessageInbound:基于消息的WebSocket实现类(带内消息),应用程序应当扩展这个类并实现其抽象方法onBinaryMessage和onTextMessage。
3、StreamInbound:基于流的WebSocket实现类(带内流),应用程序应当扩展这个类并实现其抽象方法onBinaryData和onTextData。
4、WebSocketServlet:提供遵循RFC6455的WebSocket连接的Servlet基本实现。客户端使用WebSocket连接服务端时,需要将WebSocketServlet的子类作为连接入口。同时,该子类应当实现WebSocketServlet的抽象方法createWebSocketInbound,以便创建一个inbound实例(MessageInbound或StreamInbound)。
5、WsFrame:代表完整的WebSocket框架。
6、WsHttpServletRequestWrapper:包装过的HttpServletRequest对象。
7、WsInputStream:基于WebSocket框架底层的socket的输入流。
8、 WsOutbound:提供发送消息到客户端的功能。它提供的所有向客户端的写方法都是同步的,可以防止多线程同时向客户端写入数据。

它的典型写法如下:

public class ChatWebSocketServlet extends WebSocketServlet {  private static final long serialVersionUID = 1L;  private static final String GUEST_PREFIX = "Guest";  private final AtomicInteger connectionIds = new AtomicInteger(0);  private final Set<ChatMessageInbound> connections =  new CopyOnWriteArraySet<ChatMessageInbound>();  // 创建Inbound实例,WebSocketServlet子类必须实现的方法  @Override  protected StreamInbound createWebSocketInbound(String subProtocol,  HttpServletRequest request) {  return new ChatMessageInbound(connectionIds.incrementAndGet());  }  // MessageInbound子类,完成收到WebSocket消息后的逻辑处理  private final class ChatMessageInbound extends MessageInbound {  private final String nickname;  private ChatMessageInbound(int id) {  this.nickname = GUEST_PREFIX + id;  }  // Open事件  @Override  protected void onOpen(WsOutbound outbound) {  connections.add(this);  String message = String.format("* %s %s",  nickname, "has joined.");  broadcast(message);  }  // Close事件  @Override  protected void onClose(int status) {  connections.remove(this);  String message = String.format("* %s %s",  nickname, "has disconnected.");  broadcast(message);  }  // 二进制消息事件  @Override  protected void onBinaryMessage(ByteBuffer message) throws IOException {  throw new UnsupportedOperationException(  "Binary message not supported.");  }  // 文本消息事件  @Override  protected void onTextMessage(CharBuffer message) throws IOException {  // Never trust the client  String filteredMessage = String.format("%s: %s",  nickname, HTMLFilter.filter(message.toString()));  broadcast(filteredMessage);  }  // 向所有已连接的客户端发送文本消息(广播)  private void broadcast(String message) {  for (ChatMessageInbound connection : connections) {  try {  CharBuffer buffer = CharBuffer.wrap(message);  connection.getWsOutbound().writeTextMessage(buffer);  } catch (IOException ignore) {  // Ignore  }  }  }  }  

四、javax.websocket定义的函数参数

IllegalArgumentException
No payload parameter present on the method[message]

意思是该有的参数没有,比如

  • onError()必须有Throwable参数
  • onMessage()必须有String message参数或者ByteBuffer类型的参数来接受消息

沿着抛出这个异常的异常栈逐个打开源代码,会看见容器初始化ServerEndPoint的每个细节,以及对其函数的解析.
onOpen(EndpointConfig)
onClose(CloseReason)
onError(Throwable)
onMessage(PhongMessage | InputStream | byte[] | ByteBuffer | Reader | String,boolean isLastMessage)

上面这些是有且仅能包含的参数,其中onMessage必须接受一种数据类型的数据,可以是Reader(接受文本),也可以是InputStream(二进制).PhongMessage是处理ping信息的.byte[]和ByteBuffer都是对InputStream进行了一下读取,String是对Reader进行了一下读取.
OnOpen和OnError函数不能有String类型的参数,因为它们只能包含以上类型的参数,如果OnOpen和OnError有String类型的参数,则只能是@PathParam注解的String类型的参数,否则报错A parameter of type [class java.lang.String] was found on method[error] of class [java.lang.reflect.Method] that did not have a @PathParam annotation

五、TooTallNate-java-websocket

这个库100%用Java实现,基于nio。它包含了一个websocket服务器和一个websocket客户端。官方仓库包含丰富的代码示例。这个库并不符合javax.websocket接口,它纯粹是民间的websocket实现。
服务器端需要实例化WebSocketServer这个类,可以覆盖它的onOpen,onMessage等函数。
客户端除了可以是网页,也可以是Java。用Java实现websocket客户端需要实例化WebSocketClient这个类。

Tomcat的websocket实现能够很好地跟整个web应用融为一体,比如websocket和web应用可以共用8080端口。如果用TooTallNate-java-websocket,那就必须用两个端口了。

转载于:https://www.cnblogs.com/weiyinfu/p/6287117.html

websocket初探相关推荐

  1. Spring WebSocket初探2 (Spring WebSocket入门教程)

    2019独角兽企业重金招聘Python工程师标准>>> WebSocket前端准备 SockJS: SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器不支持 W ...

  2. 【转】WebSocket初探

    定义: 遵循RFC6544协议的通信协议.Webcoket协议和http协议属于并行关系,但是websocket是以http协议为基础开发出来的(微软用IhttpHandler接口中同时处理这两种协议 ...

  3. 【WebSocket初探 】

    众所周知,socket是编写网络通信应用的基本技术,网络数据交换大多直接或间接通过socket进行.对于直接使用socket的client与服务端,一旦连接被建立则均可主动向对方传送数据,而对于使用更 ...

  4. Bookmarks(三)

    Bookmarks 书签栏 tooltips提示效果,支持点击与经过显示,位置和效果可以自定义 - CSDN博客 疯狂的小萝卜头 - 博客园 [Kettle从零开始]第九弹之Kettle定时任务介绍 ...

  5. c# websocket 心跳重连_初探和实现websocket心跳重连(npm: websocket-heartbeat-js) - 子慕大诗人 - 博客园...

    (event) { heartCheck.reset(); 如上代码,heartCheck 的 reset和start方法主要用来控制心跳的定时. 什么条件下执行心跳: 当onopen也就是连接成功后 ...

  6. 网页实时聊天之PHP如何实现websocket

    网页实时聊天之PHP如何实现websocket 一.总结 一句话总结: 应用 PHP 的 socket 函数库:PHP 的 socket 函数库跟 C 语言的 socket 函数非常类似 PHP 实现 ...

  7. 【CSS3初探之变形与动画】令人惊叹的CSS3

    前言 这个标题比较狗血了,我一直知道CSS3可以做很多事情,但是我昨天看到一个人用CSS3华丽的画了一个太极八卦! 若是这个还可以接受,那么我今天就看见一个人用CSS3画了一个叮当猫!!!我突然就在想 ...

  8. 云原生时代, Kubernetes 多集群架构初探

    为什么我们需要多集群? 近年来,多集群架构已经成为"老生常谈".我们喜欢高可用,喜欢异地多可用区,而多集群架构天生就具备了这样的能力.另一方面我们也希望通过多集群混合云来降低成本, ...

  9. websocket 历史及使用详解

    一.阅前热身 什么是keep-alive 1.keep-alive只是客户端的一种建议 我们打开百度首页,进一步查看header. image_1b2idfp2k4ecu8pagh1mkutf39.p ...

最新文章

  1. TimeQuest学习之三------外部寄存器模型
  2. build的时候出错,fatal error LNK1103
  3. JDBC——数据库的隔离级别
  4. 关于__getattribute__
  5. flink 不设置水印_区分理解Flink水印延迟与窗口允许延迟的概念
  6. 一张图学会python 3_一张图学会Python?想啥呢?!
  7. linux中 ls |wc -l
  8. response和request
  9. 层级 z-index 透明opacity
  10. 视频实现blob加密
  11. Cmake入门(1)cmake安装,创建第一个工程,引入头文件
  12. ubuntu升级显卡驱动
  13. linux 串口 ~(icanon,linux 串口uart的使用详解
  14. 免费图片库网站推荐(国外高清可商用)
  15. 网络系统高可用是几个9?
  16. 丝印代码html,常用贴片二三极管丝印 印字 代码
  17. DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (xxx.xxx.com)\n 报错解决
  18. Bash 破壳漏洞Shellshock (CVE-2014-6271)复现
  19. 无人机——舵机篇(七)
  20. echarts 横纵坐标设置

热门文章

  1. vs2017 + miniUI 后端框架使用
  2. [LeetCode] 118. Pascal's Triangle Java
  3. iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
  4. c++11 数值类型和字符串的相互转换
  5. JavaScript游戏之是男人就飞10000米
  6. java编码规范日常积累(持续更新)
  7. 软件设计师18-系统开发和运行01
  8. 6-4 开班简介1
  9. 股票资金净流入和净流出
  10. ajax 购物车 c#,c#购物车功能实现及收藏功能实现