• 利用websocket实现android消息推送


      前段时间做一个项目,需要android客户端作为管理工具与web服务器后台实时交互,想了很多方法,包括androidpn、openfire+smack、xmpp协议,要么太繁琐,要么无法满足实时性。想来还是用socket,经人提醒想到了websocket。

     
        websocket协议是近些年随html5发展而诞生的,主要用于解决web服务器与客户端无法双向交互的问题。如今已经被W3C收入标准协议。
        服务器支持:tomcat、jetty的最新版本都已支持websocket;如果不想更换现有服务器,也可用spring4.0作为替代。据说新版本的jre将收入websocket类,没具体接触。
        客户端支持:目前的主流浏览器都已经实现了websocket,但由于前期协议版本变化太快,很多厂商没有跟上。android默认浏览器就不支持websocket,IE也直到IE10才支持。
     
        网上已有通过html实现websocket client的例子,这里我们用java实现客户端连接。废话不说,上Demo:
     
    1.服务器端
    服务器用了tomcat 7.0,直接使用tomcat的websocket实现
    1)连接管理类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    import java.io.IOException;
    import java.nio.CharBuffer;
    import java.util.ArrayList;
    import java.util.List;
    import org.apache.catalina.websocket.MessageInbound;
    import org.apache.catalina.websocket.WsOutbound;
     
    public class MessageCenter
    {
        private static MessageCenter        instance           = new MessageCenter();
     
        private List<MessageInbound>        socketList;
     
        private MessageCenter()
        {
            this.socketList = new ArrayList<MessageInbound>();
        }
     
        public static MessageCenter getInstance()
        {
            return instance;
        }
     
        public void addMessageInbound(MessageInbound inbound)
        {
            socketList.add(inbound);
        }
     
        public void removeMessageInbound(MessageInbound inbound)
        {
            socketList.remove(inbound);
        }
     
        public void broadcast(CharBuffer msg) throws IOException
        {
            for (MessageInbound messageInbound : socketList)
            {
                CharBuffer buffer = CharBuffer.wrap(msg);
                WsOutbound outbound = messageInbound.getWsOutbound();
                outbound.writeTextMessage(CharBuffer.wrap("broadcasting:" + msg));
                // outbound.writeTextMessage(buffer);
                outbound.flush();
            }
        }
    }
     
    2)消息入口类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.util.Date;
     
    import org.apache.catalina.websocket.MessageInbound;
    import org.apache.catalina.websocket.WsOutbound;
     
    public class MyMessageInbound extends MessageInbound {
     
        @Override
        protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
            // TODO Auto-generated method stub
             
        }
     
        @Override
        protected void onTextMessage(CharBuffer msg) throws IOException {
            System.out.println("Received:"+msg);
            MessageCenter.getInstance().broadcast(msg);
             
        }
     
        @Override
        protected void onClose(int status) {
            System.out.println("close:"+new Date());
            MessageCenter.getInstance().removeMessageInbound(this);
            super.onClose(status);
        }
     
        @Override
        protected void onOpen(WsOutbound outbound) {
            System.out.println("open :"+new Date());
            super.onOpen(outbound);
            MessageCenter.getInstance().addMessageInbound(this);
        }
    }
    3)Websocket servlet
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import javax.servlet.http.HttpServletRequest;
     
    import org.apache.catalina.websocket.StreamInbound;
    import org.apache.catalina.websocket.WebSocketServlet;
     
    public class MeWebSocketServlet extends WebSocketServlet
    {
     
        private static final long serialVersionUID = -7178893327801338294L;
     
        @Override
        protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request)
        {
            System.out.println("##########client login#########");
            return new MeMessageInbound();
        }
     
    }
    4)添加servlet到web.xml
            < servlet>
                   < servlet-name> android</ servlet-name >
                   < servlet-class> MyWebSocketServlet </servlet-class >
            </ servlet>
            < servlet-mapping>
                   < servlet-name> android</ servlet-name >
                   < url-pattern> *.do</ url-pattern >
            </ servlet-mapping>


    2.客户端
        客户端使用java实现websocket client,
        网上有人实现了Java-websocket:https://github.com/TooTallNate/Java-WebSocket 可以取得源码,用maven编译。
        最新jar包下载地址:
     
        引用jar包后,实现简单消息连接:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    import java.net.URI;
    import java.net.URISyntaxException;
     
    import org.java_websocket.client.WebSocketClient;
    import org.java_websocket.drafts.Draft;
    import org.java_websocket.drafts.Draft_10;
    import org.java_websocket.drafts.Draft_17;
    import org.java_websocket.framing.Framedata;
    import org.java_websocket.handshake.ServerHandshake;
     
    /** This example demonstrates how to create a websocket connection to a server. Only the most important callbacks are overloaded. */
    public class ExampleClient extends WebSocketClient {
     
            public ExampleClient( URI serverUri , Draft draft ) {
                    super( serverUri, draft );
            }
     
            public ExampleClient( URI serverURI ) {
                    super( serverURI );
            }
     
            @Override
            public void onOpen( ServerHandshake handshakedata ) {
                    System.out.println( "opened connection" );
                    // if you plan to refuse connection based on ip or httpfields overload: onWebsocketHandshakeReceivedAsClient
            }
     
            @Override
            public void onMessage( String message ) {
                    System.out.println( "received: " + message );
            }
     
            @Override
            public void onFragment( Framedata fragment ) {
                    System.out.println( "received fragment: " new String( fragment.getPayloadData().array() ) );
            }
     
            @Override
            public void onClose( int code, String reason, boolean remote ) {
                    // The codecodes are documented in class org.java_websocket.framing.CloseFrame
                    System.out.println( "Connection closed by " + ( remote ? "remote peer" "us" ) );
            }
     
            @Override
            public void onError( Exception ex ) {
                    ex.printStackTrace();
                    // if the error is fatal then onClose will be called additionally
            }
     
            public static void main( String[] args ) throws URISyntaxException {
                    ExampleClient c = new ExampleClient( new URI( "ws://localhost:8080/myweb/android.do" ), new Draft_17() );
                    c.connect();
            }
     
    }
    注意,连接中使用的new Draft_17()就是使用的协议version,Tomcat 7.0的协议版本需要高于Draft_17。
     
    总结websocket的利弊
    优点:
    与socket相比,可以节省额外的端口占用,直接使用一个公网域名访问。另外协议对报文的流量消耗做了优化。
     
    缺点:
    毕竟websocket底层也是socket连接,因而当大并发用户连接时目测会消耗较多资源。
     
    参考:
  • 相关阅读:
    无法将类型“XXX”隐式转换为“XXX[]”(Cannot implicitly convert type 'XXX' to 'XXX[]')
    VS2010验证时出错。HRESULT = '8000000A'
    Linux Command Tips
    RealVNC 使用手册
    PL/SQL Developer自动补全SQL技巧
    Install dnsutils(dig, nslookup, host) On iPhone
    asp.net压缩图片
    Discuz论坛密码加密方式详解
    三种SQL分页法效率分析
    Mysql数据库服务器配置文件/etc/my.cnf的详细配置
  • 原文地址:https://www.cnblogs.com/georgewangii/p/4511275.html
Copyright © 2020-2023  润新知