一:为什么要用websocket

  Web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说,比如说在线游戏、在线证券、设备监控、新闻在线播报、RSS 订阅推送等等,当客户端浏览器准备呈现这些信息的时候,这些信息在服务器端可能已经过时了。

  所以保持客户端和服务器端的信息同步是实时 Web 应用的关键要素。

二:netty框架搭建websocket服务器

  本文简述了一个简单web聊天室功能。

1.下载所依赖jar包

  netty-3.6.6.Final.jar  这里的版本最好下载比较新的版本。  

2.新建jar工程

  创建四个类:Globle.java,WebSocketServer.java,WebSocketServerHandler.java,WebSocketServerPipelineFactory.java

Globle.java

package com.hundsun.websocket;

import java.util.HashSet;
import java.util.Set;

import org.jboss.netty.channel.Channel;

public class Globle {
    public static Set<Channel> ctxs= new HashSet<>();
}

  

WebSocketServer.java

package com.hundsun.websocket;

import java.net.InetSocketAddress;



import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class WebSocketServer {
    private final int port;
    public static ChannelHandlerContext ctx = null;
    public WebSocketServer(int port){
        this.port = port;
    }
    public void run(){
        ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));   
        bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());  
        System.out.println();
        bootstrap.bind(new InetSocketAddress(port));   
        System.out.println("Web socket server started at port " + port + '.');  
        System.out.println("Open your browser and navigate to http://localhost:" + port + '/'); 
    }
     public static void main(String[] args) {  
            int port;  
            if (args.length > 0) {  
                port = Integer.parseInt(args[0]);  
            } else {  
                port = 8081;  
            }  
            new WebSocketServer(port).run();                
        }  
}

 

WebSocketServerHandler.java

package com.hundsun.websocket;
import java.util.Iterator;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
public class WebSocketServerHandler  extends SimpleChannelUpstreamHandler{
    private static final String WEBSOCKET_PATH = "/websocket";  
    private WebSocketServerHandshaker handshaker;  
    @Override
    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {
        Globle.ctxs.add(ctx.getChannel());
        System.out.println(ctx.getChannel()+"s");
    }
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
            throws Exception {
        Globle.ctxs.remove(ctx.getChannel());
    }
    @Override  
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {  
        Object msg = e.getMessage(); 
        String receivedMsg = msg.toString();
        receivedMsg = receivedMsg.substring(receivedMsg.indexOf('(')+1, receivedMsg.indexOf(')'));  
        String[] RealMsg = receivedMsg.split(":");
        if(!RealMsg[1].trim().equals("")){
            if (msg instanceof HttpRequest) {  
                handleHttpRequest(ctx, (HttpRequest) msg);
            } else if (msg instanceof WebSocketFrame) {
                Iterator<Channel> MyCtx = Globle.ctxs.iterator();
                while(MyCtx.hasNext()){
                    MyCtx.next().write(new TextWebSocketFrame(RealMsg[1]));
                }    
                handleWebSocketFrame(ctx, (WebSocketFrame) msg);                 
            }  
        }
    }    
    private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {  
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(  
                getWebSocketLocation(req), null, false);  
        handshaker = wsFactory.newHandshaker(req);  
        if (handshaker == null) {  
            wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());  
        } else {  
            handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);  
        }  
        WebSocketServer.ctx = ctx;  
    }  
    private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { 
        // Check for closing frame  
        if (frame instanceof CloseWebSocketFrame) {  
            handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);  
              
            WebSocketServer.ctx = null;  
            return;  
        }  
    }  
    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
        e.getCause().printStackTrace();  
        e.getChannel().close();     
        WebSocketServer.ctx = null;  
    }  
  
    private static String getWebSocketLocation(HttpRequest req) {  
        return "ws://" + req.getHeader(HOST) + WEBSOCKET_PATH;
    }  
}

 

WebSocketServerPipelineFactory.java

package com.hundsun.websocket;

import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;

public class WebSocketServerPipelineFactory implements ChannelPipelineFactory{

    @Override
    public ChannelPipeline getPipeline() throws Exception {
        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;  
    }
    
}

 运行main函数即可启动websocket服务器:

 

三:web客户端

客户端包括文件:js/websocket.js,css/websocket.css,websocket.html

再在img文件夹中添加一个psd.jpg图片文件  img/psd.jpg

js/websocket.js

document.addEventListener("DOMContentLoaded", connect, false)
var socket;
function connect() {
    if (!window.WebSocket) {  
        window.WebSocket = window.MozWebSocket;  
    }  
    if (window.WebSocket) { 
        if(socket == null){
            socket = new WebSocket("ws://localhost:8081/");  
       }
        socket.onmessage = function(event) {  
             var ul = document.getElementById("chart_msg");
             var li = document.createElement("li");
             var div1 = document.createElement("div");
             var div2 = document.createElement("div");    
             var span = document.createElement("span");
             span.style.paddingLeft="20px";
             span.style.marginLeft="20px";
             span.style.width="230px";
             span.style.overflow="hidden";
               span.style.marginTop="20px";
               span.innerHTML=event.data;
               var img = document.createElement("img");
               img.src="img/psb.jpg";
             div2.style.backgroundColor="white";
             div2.style.minHeight="70px";
             div2.style.width="250px";
             div2.style.borderRadius="10px";
             div2.className="chart_text";
             div1.className="head_img";
             div1.appendChild(img);
             div2.appendChild(span);
             li.appendChild(div1);
             li.appendChild(div2);
             ul.appendChild(li);
        };  
        socket.onopen = function(event) {  
             
        };          
        socket.onclose = function(event) {  
  
        };  
    } else {  
        alert("Your browser does not support Web Socket.");  
    }  
}  
function sendContent() {
    var send_text = document.getElementById("send_text").value;
    socket.send(send_text);
}

 

css/websocket.css

.whole_area{
    position: absolute;
    width: 940px;
    height: 550px;
    left: 50%;
    top: 50%;
    margin-left: -450px;
    margin-top: -270px;
    /*background: darkgray;*/
}
.chart_friend_area{
    width: 120px;
    height: 550px;
    float: left;
    background: darkcyan;
}
.chart_area{
    width: 560px;
    height: 550px;
    background: wheat;
    padding-left: 120px;
}
.chart_msg{
    width: 560px;
    height: 370px;
/*    background: salmon;*/
    overflow: auto;
}
.chart_msg ul{
    list-style-type: none;
    margin:0;
    padding: 0;
}
.chart_msg ul li{
    margin-top: 50px;
    border-radius: 2px;
    width: 400px;
    word-break:break-all
}
.head_img{
    float: left;
    width: 35px;
    height: 35px;
    border-radius: 4px;
    overflow: hidden;
}
.chart_text{

    word-break: break-all;
    margin-left: 60px;
}
.head_img img{
    border-radius: 4px;
    width: 30px;
    height: 30px;
}
.send_msg{
    width: 560px;
    height: 110px;
    background: cadetblue;
}
.face_icon{
    width: 560px;
    height: 30px;
    background: saddlebrown;
}
.send_msg textarea{
    width: 560px;
    height: 110px;
    font: "宋体";
}
.send_clear{
    width: 560px;
    height: 40px;
    background: sandybrown;
}
.send_but{
    width: 90px;
    height: 30px;
    background: seagreen;
    float: right;
    margin-top: 5px;
    margin-right: 10px;
    text-align: center;
    line-height: 30px;
    border-radius: 5px;
}
.send_but:active{

}
.send_but:hover{
    background: seashell;
    cursor: pointer;
}

.friend_area{
    width: 220px;
    height: 550px;
    background-color: darkcyan;
    margin-top: -550px;
    margin-left:680px;
}
.close_but{
    width: 40px;
    height: 100px;
    background: skyblue;
    float: right;
    margin-top: -550px;
}

 

websocket.html

<html>
<head>
<title>websocket</title>
<script src="js/websocket.js"></script>    
<link href="css/websocket.css" rel="stylesheet" type="text/css"/>
</head>
<body>
    <div class="whole_area">
        <!---->
        <div class="chart_friend_area">
            
        </div>
        <!--中,聊天内容显示区-->
        <div class="chart_area">
            <div class="chart_msg">
                <ul id="chart_msg">
                    
                </ul>
            </div>
            <div class="face_icon">
                
            </div>
            <div class="send_msg">            
                <textarea id="send_text"></textarea>
            </div>
            <div class="send_clear">
                <a class="send_but" onclick="sendContent()" accesskey="c">
                    发送
                </a>
            </div>
        </div>
        <!--右,好友列表区-->
        <div class="friend_area">
        
        </div>
        <div class="close_but">
        
        </div>
    </div>
</body>
</html>

 

客户端效果图:

 

原创博客地址:http://www.cnblogs.com/chaizezhao/articles/5291608.html

posted on 2016-03-18 13:14  是他、就是他  阅读(6577)  评论(0编辑  收藏  举报