美文网首页
一篇文章让你学习使用websocket

一篇文章让你学习使用websocket

作者: flykyle | 来源:发表于2017-05-01 19:51 被阅读0次

    学习教程

    跟着下面两篇教程的任意一篇写一遍,WebSocket基本上就算掌握了。

    WebSocket介绍

    web应用的出现需要客户端和服务端更多的交互,http只能在客户端每次请求服务端的时候建立短暂的连接,已经不能满足需求。虽然long-poll和Ajax也可以实现服务端向浏览器发送数据,但它们这种轮询的方式存在一些弊端,比如请求延迟和http过度请求。在需要实时连接(real-time)的应用中,这种弊端更加明显。

    websocket是HTML5中新加入的内容。通过websocket(协议),每个浏览器(客户端)和服务端建立一个长连接,双方都可以随时主动地向对方发送消息。

    Java EE 7 中已经集成了websocket,通过使用注解,可以很方便地创建一个websocket应用,主要有下面五个注解:

    @ServerEndpoint:定义websocket的地址;

    @OnOpen:服务端和客户端建立连接时调用;

    @OnMessage:发送数据时调用;

    @OnClose:关闭连接时调用;

    @OnError:出错时调用。

    教程主要内容

    下面是第一篇教程的主要内容,你可以到这里下载源码。

    创建websocket服务

    @ServerEndpoint定义了websocket的服务端地址,还定义了编译发送出去的信息和解析收到的信息的类。

    package com.ws.sticker;
    
    import java.io.IOException;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    import javax.websocket.EncodeException;
    import javax.websocket.OnClose;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    @ServerEndpoint(
      value="/story/notifications",
      encoders={StickerEncoder.class}, 
      decoders={StickerDecoder.class})
    public class StoryWebSocket {
        // 保存所有的 sticker
        private static final List<Sticker> stickers = Collections.synchronizedList(new LinkedList<Sticker>()); 
        // 保存所有客户端的 session
        private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>()); 
        
        @OnMessage
        public void onMessage(Session session, Sticker sticker){
            // 有消息从客户端发送过来,保存到列表中,然后通知所有的客户端
            stickers.add(sticker);
            for(Session openSession : sessions){
                try {
                    openSession.getBasicRemote().sendObject(sticker);
                } catch (IOException | EncodeException e) {
                    sessions.remove(openSession); 
                }
            }
        }
        
        @OnOpen
        public void onOpen(Session session) throws IOException, EncodeException{
            // 有新的客户端连接时,保存此客户端的session,并且把当前所有的sticker发送给它
            sessions.add(session);
            for(Sticker sticker : stickers){
                session.getBasicRemote().sendObject(sticker);
            }
        }
        
        @OnClose
        public void onClose(Session session){
            // 有客户端断开连接时 ,从session列表中移除此客户端的session
            sessions.remove(session);
        }
    }
    
    

    定义编译类

    StickerEncoder.class编译将要发送出去的信息:将要发送的Sticker对象转化成JsonObject对象,然后通过JsonWriter发送到客户端。

    package com.ws.sticker;
    
    import java.io.IOException;
    import java.io.Writer;
    
    import javax.json.JsonObject;
    import javax.json.JsonWriter;
    import javax.json.spi.JsonProvider;
    import javax.websocket.EncodeException;
    import javax.websocket.Encoder;
    import javax.websocket.EndpointConfig;
    
    public class StickerEncoder implements Encoder.TextStream<Sticker> {
    
        @Override
        public void init(EndpointConfig config) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void encode(Sticker sticker, Writer writer) throws EncodeException, IOException {
            JsonProvider provider = JsonProvider.provider();
            JsonObject jsonSticker = provider.createObjectBuilder()
                    .add("action", "add")
                    .add("x", sticker.getX())
                    .add("y", sticker.getY())
                    .add("sticker", sticker.getImage())
                    .build();
            JsonWriter jsonWriter = provider.createWriter(writer);
            jsonWriter.write(jsonSticker);
        }
    
    }
    
    

    定义解析类

    StickerDecoder.class解析服务端收到的信息:通过Reader获得接收到的信息JsonObject,然后转化成Sticker对象。

    package com.ws.sticker;
    
    import java.io.IOException;
    import java.io.Reader;
    
    import javax.json.JsonObject;
    import javax.json.JsonReader;
    import javax.json.spi.JsonProvider;
    import javax.websocket.DecodeException;
    import javax.websocket.Decoder;
    import javax.websocket.EndpointConfig;
    
    public class StickerDecoder implements Decoder.TextStream<Sticker> {
    
        // Do not create a JsonReader object. To create readers and writes, use the
        // JsonProvider class.
    
        @Override
        public void init(EndpointConfig config) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        @Override
        public Sticker decode(Reader reader) throws DecodeException, IOException {
            JsonProvider provider = JsonProvider.provider();
            JsonReader jsonReader = provider.createReader(reader);
            JsonObject jsonSticker = jsonReader.readObject();
          
            Sticker sticker = new Sticker();
            sticker.setX(jsonSticker.getInt("x"));
            sticker.setY(jsonSticker.getInt("y"));
            sticker.setImage(jsonSticker.getString("sticker"));
            return sticker;
        }
    
    }
    
    

    创建websocket客户端

    var socket = null;
    
    function initialize() {
        ...
        // 连接到websocket服务端
        socket = new WebSocket('ws://localhost:8080/learn/story/notifications');
        // 定义接收消息时执行的方法
        socket.onmessage = onSocketMessage;
    }
    
    function onSocketMessage(event) {
        if(event.data){
            var receivedSticker = JSON.parse(event.data);
            log("Received Object: " + JSON.stringify(receivedSticker));
            
            ...
        }
    }
    
    window.onload = initialize;
    

    观察现象

    运行Java web程序,在多个浏览器中打开 http://localhost:8080/learn/story/notifications ,当其中一个浏览器的内容改变的时候,其他浏览器也会相应地改变。

    总结

    通过上面的练习,主要学到了:

    • 通过 java API 创建 websocket server;
    • 创建JSON 编译、解析类读写socket的数据;
    • 使用JavaScript创建 websocket client。

    相关文章

      网友评论

          本文标题:一篇文章让你学习使用websocket

          本文链接:https://www.haomeiwen.com/subject/qglqtxtx.html