Netty实现webSocket

发表时间:2017-09-13 14:58:36 浏览量( 12 ) 留言数( 0 )

学习目标:

1、了解WebSocket 

2、了解WebSocket的初步实现


学习过程:

   WebSocket 在客户端和服务器之间提供了真正的双向数据交换。要想向你的应用程序中添加对于WebSocket 的支持,你需要将适当的客户端或者服务器WebSocket ChannelHandler 添加到ChannelPipeline 中。这个类将处理由WebSocket 定义的称为帧的特殊消息类型。

WebSocketFrame 可以被归类为数据帧或者控制帧。

BinaryWebSocketFrame 数据帧:二进制数据

TextWebSocketFrame 数据帧:文本数据

ContinuationWebSocketFrame 数据帧:属于上一个BinaryWebSocketFrame 或者TextWeb-

SocketFrame 的文本的或者二进制数据

CloseWebSocketFrame 控制帧:一个CLOSE 请求、关闭的状态码以及关闭的原因

PingWebSocketFrame 控制帧:请求一个PongWebSocketFrame

PongWebSocketFrame 控制帧:对PingWebSocketFrame 请求的响应

    因为Netty主要是一种服务器端的技术,所以在这里我们重点创建WebSocket服务器,展示了一个使用WebSocketServerProtocolHandler的简单示例,这个类处理协议升级握手,以及3 种控制帧——Close、Ping和Pong。Text和Binary数据帧将会被传递给下一个(由你实现的)ChannelHandler进行处理。

public class WebSocketServerInitializer extends ChannelInitializer<Channel> {


	@Override
	protected void initChannel(Channel ch) throws Exception {
		ch.pipeline().addLast(new HttpServerCodec(), new HttpObjectAggregator(65536),
				new WebSocketServerProtocolHandler("/websocket"), new TextFrameHandler(),new BinaryFrameHandler(),new ContinuationFrameHandler(),new CloseFrameHandler());
	}

	public static final class TextFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
		
		@Override
		public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
			System.out.println("TextFrameHandler:channelRead0:" + msg.text());
		}
		
		@Override
		public void channelActive(ChannelHandlerContext ctx) throws Exception { 
			 Channel incoming = ctx.channel();
			 System.out.println("Client:" + incoming.remoteAddress() + "在线");
		}

		@Override
		public void channelInactive(ChannelHandlerContext ctx) throws Exception {
			Channel incoming = ctx.channel();
			System.out.println("Client:" + incoming.remoteAddress() + "掉线");
		}

		@Override
		public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
			Channel incoming = ctx.channel();
			System.out.println("Client:" + incoming.remoteAddress() + "异常");
			// 当出现异常就关闭连接
			cause.printStackTrace();
			ctx.close();
		}
		
	}

	public static final class BinaryFrameHandler extends SimpleChannelInboundHandler<BinaryWebSocketFrame> {
		@Override
		public void channelRead0(ChannelHandlerContext ctx, BinaryWebSocketFrame msg) throws Exception {
			System.out.println("BinaryFrameHandler:channelRead0");
		}
	}

	public static final class ContinuationFrameHandler extends SimpleChannelInboundHandler<ContinuationWebSocketFrame> {
		@Override
		public void channelRead0(ChannelHandlerContext ctx, ContinuationWebSocketFrame msg) throws Exception {
			System.out.println("ContinuationFrameHandler:channelRead0");
		}
	}
	
	
	public static final class CloseFrameHandler extends SimpleChannelInboundHandler<CloseWebSocketFrame > {

		@Override
		protected void channelRead0(ChannelHandlerContext ctx, CloseWebSocketFrame msg) throws Exception {
			System.out.println("CloseFrameHandler:channelRead0");
		}
	}


	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		Channel incoming = ctx.channel();
		System.out.println("Client:" + incoming.remoteAddress() + "异常");
		// 当出现异常就关闭连接
		cause.printStackTrace();
		ctx.close();
	}

}


客户端代码就是js了,比较简单:

<!DOCTYPE html>  
<meta charset="utf-8" />  
<title>WebSocket Test</title>  
<script language="javascript"type="text/javascript">  
    var wsUri ="ws://localhost/websocket"; 
    var output;  
    
    function init() { 
        output = document.getElementById("output"); 
        testWebSocket(); 
    }  
 
    function testWebSocket() { 
        websocket = new WebSocket(wsUri); 
        websocket.onopen = function(evt) { 
            onOpen(evt) 
        }; 
        websocket.onclose = function(evt) { 
            onClose(evt) 
        }; 
        websocket.onmessage = function(evt) { 
            onMessage(evt) 
        }; 
        websocket.onerror = function(evt) { 
            onError(evt) 
        }; 
    }  
 
    function onOpen(evt) { 
        writeToScreen("CONNECTED"); 
        doSend("WebSocket rocks"); 
    }  
 
    function onClose(evt) { 
        writeToScreen("DISCONNECTED"); 
    }  
 
    function onMessage(evt) { 
        writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>'); 
        websocket.close(); 
    }  
 
    function onError(evt) { 
        writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data); 
    }  
 
    function doSend(message) { 
        writeToScreen("SENT: " + message);  
        websocket.send(message); 
    }
    
    function doClose(){
    	websocket.close();
    }
 
    function writeToScreen(message) { 
        var pre = document.createElement("p"); 
        pre.style.wordWrap = "break-word"; 
        pre.innerHTML = message; 
        output.appendChild(pre); 
    }  
 
    window.addEventListener("load", init, false);  
</script>  
<h2>WebSocket Test</h2>  
<div id="output"></div>  

<input  type="button" value="发送"  onclick="doSend('hello')" />
|
<input  type="button" value="关闭"  onclick="doClose()" />

</html>