`
hyshucom
  • 浏览: 802658 次
文章分类
社区版块
存档分类
最新评论

跨平台移动开发实战(七)------服务器端快速搭建

 
阅读更多

客户端与服务端基于HTTP和WebSocket网络协议来通讯,其中HTTP用于从客户端向服务端的请求,WebSocket用于从服务端向客户端的推送,因此服务器端需要支持HTTP和WebSocket两种协议。HTTP好说,所有Web服务器都支持,而支持WebSocket的倒不多。

.Net和Nodejs俺不熟,就不作评论,Tomcat 7在最新版本里加入对Websocket支持,但我需要更为轻量级的方案,最好是内嵌,因此Netty就成了我首选。Netty源码里有websocket的Samples,我就是直接在samples上进行修改,总结下来需要如下几步:

  1. 打开网络端口
    (new Thread(new Runnable(){
    	@Override
    	public void run() {
    		ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
                    Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
            // Set up the event pipeline factory.
            bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
            int port = 8080;
            // Bind and start to accept incoming connections.
            bootstrap.bind(new InetSocketAddress(port));
            System.out.println("Web socket server started at port " + port + '.');
    	}
    })).start();
  2. 创建处理数据流的pipeline,特别是加入Websocket的handler
    public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
        public ChannelPipeline getPipeline() throws Exception {
            // Create a default pipeline implementation.
            ChannelPipeline pipeline = pipeline();
            pipeline.addLast("decoder", new HttpRequestDecoder());
            pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
            pipeline.addLast("encoder", new HttpResponseEncoder());
            pipeline.addLast("handler", new WebSocketServerHandler());
            return pipeline;
        }
    }
  3. 实现在WebSocketServerHandler里实现messageReceived,接收网络数据。这里数据分为HTTP和WebSocket两种,如何是HTTP,那说明是处理最开始的Handshake阶段,这是需要为WebSocket建立握手
    // Handshake
    WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
            this.getWebSocketLocation(req), null, false);
    this.handshaker = wsFactory.newHandshaker(req);
    if (this.handshaker == null) {
        wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
    } else {
        this.handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
    }
    如果是WebSocketFrame,则接收客户端发来的message
    String request = ((TextWebSocketFrame) frame).getText();
  4. 向客户端推送数据,这里只要是channel没关,并且能拿到channel对象即可
    ctx.getChannel().write(new TextWebSocketFrame("some message"));
  5. 实现channelOpen、channelClosed等方法,实现对网络连接整个生命周期的监控

值得注意的是目前WebSocket的实现对二进制流支持不够好,因此当需要服务端向客户端推送类似与文件类IO流时,我采取的折中方案,就是先让websocket向客户端发通知,然后再让客户端向服务端请求文件下载,当然这样的代价就是两次连接,如果有更好的方案请推荐给我。

对于HTTP,Netty从原理上说是支持的,不过支持得不够好,最新的不稳定版本才有HTTP Request的解析支持,我也没太多时间来写这块,于是乎又找了另外一个可以内嵌的Web服务器Jetty来支持HTTP和servlet,当然我用了比较老版本的Jetty 6,这个版本比较轻量,内嵌比较简单,几行代码就可以打开网络端口并支持servlet:

(new Thread(new Runnable(){
	@Override
	public void run() {
		int port = 8081;
		Server server = new Server(port);
		Context root = new Context(server,"/",Context.SESSIONS);
		root.addServlet(new ServletHolder(new LoginSTServlet()), "/login");
		try{
			server.start();
	        System.out.println("Http server started at port " + port + '.');
		}catch(Exception err){
			err.printStackTrace();
		}
	}
})).start();
这样,几个类就搭起了服务端,当然这只是快速开始,服务端的建设远不止这些,比如security和数据压缩等,这些我单独拿出来详细分析


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics