带你玩转Netty(三)之WebSocket
来源:互联网 发布:js获取本地时间 编辑:程序博客网 时间:2024/05/17 00:54
摘要
前面两篇文章分别给大家介绍了原理篇,应用篇,这回给大家介绍WebSocket在Netty中的应用。
什么是WebSocket
传统的Http协议只能客户端发起通信,而不能做到服务端主动通知。这里可能有人说可以采用long polling,也就是客户端不断的向服务端请求,获取新数据,虽然能解决问题,但效率低下,浪费资源,只能说是笨办法。所以WebSocket就出现了。
webSocket协议是2008年诞生,2011年成为国际标准,所有浏览器都支持。他最大的特点就是服务端和客户端全双工通信,即客户端能主动给服务端发消息,服务端也能给客户端主动发消息。
该协议默认端口80或者443 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL,例如:
ws://example.com:8080/path
不管是HTTP和Websocket都是建立在TCP协议之上, 如下图:
所不一样的就是与服务端交互流程上有所区别,如下图:
从图中可以看到,传统的Http只有请求和响应,而WebSocket分为这几个阶段。
1. 握手阶段(handshake)
客户端发起握手请求,如下报文:
服务端响应握手请求,如下报文:
可以看出握手阶段采用的是HTTP协议,能通过http的各种代理服务器,与http协议有良好的兼容性。
2. 长连接阶段
通过握手从http协议升级到了websocket协议,
这个时你可以向服务端发送任何消息,服务也可以向你主动推送消息。数据格式可以根据业务需要与服务端商议,灵活度高,通信效率高效。
3. 连接关闭
客户端与服务端其中一方发起关闭即为关闭。
WebSocket应用
我们主要使用Netty框架来实现服务端,采用js来实现客户端。
服务端实现
主要使用了 Netty-socketio 这个开源框架,基于Netty框架里面封装了WebSocket的协议解析,响应,如果你是maven工程,可以在pom.xml中添加dependecy
<dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.12</version></dependency>
应用起来比较简单,如下代码
public static void main( String[] args ) throws InterruptedException { final SocketIOServer server = new SocketIOServer(loadSocketIOConfig(doc)); // (1) // 启动login final SocketIONamespace ns = server.addNamespace("/echo"); // (2) EchoConnectListener listener = new EchoConnectListener(); // (3) EchoEventListener evtlistener = new EchoEventListener(); // (4) ns.addConnectListener(listener); ns.addDisconnectListener(listener); ns.addEventListener(WebEventMessage.EVT_TAG, WebEventMessage.class, evtlistener); // (5) server.start(); logger.info("============>WSServer started ... ok");}private static Configuration loadSocketIOConfig(Document doc) { Configuration config = new Configuration(); config.setHostname(getNodeStr(doc, "host")); config.setPort(getNodeInt(doc, "port")); config.setBossThreads(getNodeInt(doc, "bossThreads")); config.setWorkerThreads(getNodeInt(doc, "workerThreads")); //config.setUseLinuxNativeEpoll(PlatformDependent.isWindows() ? false : true); return config;}
public class EchoEventListener implements DataListener<WebEventMessage> { private static final Logger logger = LoggerFactory.getLogger(EchoEventListener.class); public EchoEventListener() { } @Override public void onData(SocketIOClient client, WebEventMessage data, AckRequest ackSender) throws Exception { System.out.println("message:" + data.getMessage()); WebEventMessage hello = new WebEventMessage(); JSONObject object = new JSONObject(data.getMessage()); if (UserTokenMgr.getInstance().verify(object.getInt("userid"), object.getString("token"))) { hello.setMessage("login success"); } else { hello.setMessage("login failed"); } client.getNamespace().getBroadcastOperations().sendEvent(WebEventMessage.EVT_TAG, hello); // (6) }}
加载配置,实例化SocketIOServer, 配置主要是ip,端口,处理线程和工作线程数量。
加入一个命名为echo的Namespace,这个具体访问是在url体现的,如下:
ws://example.com:8080/echo
只要是这个url的访问,都会在这个namespace处理。
创建连接监听器
创建业务消息处理器
将连接监听器,和业务消息处理器添加到 namespace, 在添加业务消息处理器时,需要指定消息协议对象,比如 WebEventMessage。
服务端接收数据,并返回给客户端。
客户端实现
客户端这里采用的是socket.io, 采用js实现,与前端对接。
var socket = io.connect('http://127.0.0.1:8080/echo');socket.on('connect', function() { output('<span class="connect-msg">Client has connected to the server!</span>');}); // (1)socket.on('message', function(data) { output('<span class="username-msg"> echo' + ':</span> ' + data.message);}); // (2)socket.on('disconnect', function() { output('<span class="disconnect-msg">The client has disconnected!</span>');}); // (3)
发送数据
var message = JSON.stringify(jsonmsg);var cmd = 1;var jsonObject = {'@class': 'WebEventMessage', cmd:cmd, message: message}; socket.emit('message', jsonObject, function(arg1, arg2) {}); // (4)
connect连接建立后回调函数。
message用于指定收到服务器数据后的回调函数。
disconnect断开连接后回调函数。
emit向服务器发送消息。
总结
基于Netty的websocket,在提供良好性能的同时大大增强直播,聊天等产品在前端页面的体验。
参考链接
Sokect.io
netty-socketio
WebSocket 教程
欢迎关注公众号
- 带你玩转Netty(三)之WebSocket
- 带你玩转Netty(一)
- 带你玩转Netty(二)
- 带你玩转JavaWeb之三-JS代码实战
- 带你轻松玩转Git--图解三区结构
- Netty之WebSocket开发
- 带你玩转Github
- 带你玩转二维码
- 带你玩转 UIAlertController
- 带你玩转JavaWeb之五-响应式开发
- 带你玩转JavaWeb之六-Mysql数据库
- Netty精粹之玩转NIO缓冲区
- Netty之WebSocket协议开发
- Netty之WebSocket协议开发
- 手把手叫你玩转网络编程系列之三
- 手把手叫你玩转网络编程系列之三
- UWA GOT | 三分钟带你玩转Unity性能优化!
- Android三种姿势带你玩转360度全景图功能
- JAVA反射机制的应用场景
- 【EntityFramework 6.1.3】个人理解与问题记录(3)
- Codeforces Round #416 (Div. 2)
- 程序员面试金典(1):确定字符互异(python)
- NYOJ32组合数
- 带你玩转Netty(三)之WebSocket
- 网页开发需要注意什么?
- JavaScript定时器的几种方法
- SPOJ
- codeforces 812C Sagheer and Nubian Market (二分)
- JavaScript 中 for 循环的独特之处
- jQuery growl插件
- JQuery初识
- BZOJ 1625: [Usaco2007 Dec]宝石手镯