带你玩转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)    }}
  1. 加载配置,实例化SocketIOServer, 配置主要是ip,端口,处理线程和工作线程数量。

  2. 加入一个命名为echo的Namespace,这个具体访问是在url体现的,如下:

    ws://example.com:8080/echo

    只要是这个url的访问,都会在这个namespace处理。

  3. 创建连接监听器

  4. 创建业务消息处理器

  5. 将连接监听器,和业务消息处理器添加到 namespace, 在添加业务消息处理器时,需要指定消息协议对象,比如 WebEventMessage。

  6. 服务端接收数据,并返回给客户端。

客户端实现

客户端这里采用的是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)
  1. connect连接建立后回调函数。

  2. message用于指定收到服务器数据后的回调函数。

  3. disconnect断开连接后回调函数。

  4. emit向服务器发送消息。

总结

基于Netty的websocket,在提供良好性能的同时大大增强直播,聊天等产品在前端页面的体验。

参考链接

Sokect.io

netty-socketio

WebSocket 教程

欢迎关注公众号

原创粉丝点击