websocket初探
过去都是使用浏览器端插件(如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初探相关推荐
- Spring WebSocket初探2 (Spring WebSocket入门教程)
2019独角兽企业重金招聘Python工程师标准>>> WebSocket前端准备 SockJS: SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器不支持 W ...
- 【转】WebSocket初探
定义: 遵循RFC6544协议的通信协议.Webcoket协议和http协议属于并行关系,但是websocket是以http协议为基础开发出来的(微软用IhttpHandler接口中同时处理这两种协议 ...
- 【WebSocket初探
】
众所周知,socket是编写网络通信应用的基本技术,网络数据交换大多直接或间接通过socket进行.对于直接使用socket的client与服务端,一旦连接被建立则均可主动向对方传送数据,而对于使用更 ...
- Bookmarks(三)
Bookmarks 书签栏 tooltips提示效果,支持点击与经过显示,位置和效果可以自定义 - CSDN博客 疯狂的小萝卜头 - 博客园 [Kettle从零开始]第九弹之Kettle定时任务介绍 ...
- c# websocket 心跳重连_初探和实现websocket心跳重连(npm: websocket-heartbeat-js) - 子慕大诗人 - 博客园...
(event) { heartCheck.reset(); 如上代码,heartCheck 的 reset和start方法主要用来控制心跳的定时. 什么条件下执行心跳: 当onopen也就是连接成功后 ...
- 网页实时聊天之PHP如何实现websocket
网页实时聊天之PHP如何实现websocket 一.总结 一句话总结: 应用 PHP 的 socket 函数库:PHP 的 socket 函数库跟 C 语言的 socket 函数非常类似 PHP 实现 ...
- 【CSS3初探之变形与动画】令人惊叹的CSS3
前言 这个标题比较狗血了,我一直知道CSS3可以做很多事情,但是我昨天看到一个人用CSS3华丽的画了一个太极八卦! 若是这个还可以接受,那么我今天就看见一个人用CSS3画了一个叮当猫!!!我突然就在想 ...
- 云原生时代, Kubernetes 多集群架构初探
为什么我们需要多集群? 近年来,多集群架构已经成为"老生常谈".我们喜欢高可用,喜欢异地多可用区,而多集群架构天生就具备了这样的能力.另一方面我们也希望通过多集群混合云来降低成本, ...
- websocket 历史及使用详解
一.阅前热身 什么是keep-alive 1.keep-alive只是客户端的一种建议 我们打开百度首页,进一步查看header. image_1b2idfp2k4ecu8pagh1mkutf39.p ...
最新文章
- TimeQuest学习之三------外部寄存器模型
- build的时候出错,fatal error LNK1103
- JDBC——数据库的隔离级别
- 关于__getattribute__
- flink 不设置水印_区分理解Flink水印延迟与窗口允许延迟的概念
- 一张图学会python 3_一张图学会Python?想啥呢?!
- linux中 ls |wc -l
- response和request
- 层级 z-index 透明opacity
- 视频实现blob加密
- Cmake入门(1)cmake安装,创建第一个工程,引入头文件
- ubuntu升级显卡驱动
- linux 串口 ~(icanon,linux 串口uart的使用详解
- 免费图片库网站推荐(国外高清可商用)
- 网络系统高可用是几个9?
- 丝印代码html,常用贴片二三极管丝印 印字 代码
- DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (xxx.xxx.com)\n 报错解决
- Bash 破壳漏洞Shellshock (CVE-2014-6271)复现
- 无人机——舵机篇(七)
- echarts 横纵坐标设置
热门文章
- vs2017 + miniUI 后端框架使用
- [LeetCode] 118. Pascal's Triangle Java
- iOS开发-retain/assign/strong/weak/copy/mutablecopy/autorelease区别
- c++11 数值类型和字符串的相互转换
- JavaScript游戏之是男人就飞10000米
- java编码规范日常积累(持续更新)
- 软件设计师18-系统开发和运行01
- 6-4 开班简介1
- 股票资金净流入和净流出
- ajax 购物车 c#,c#购物车功能实现及收藏功能实现