netty與websocket通信demo
netty v3.9.4
websocket連接建立前,客戶端需要與服務器進行握手(http協議) 確認websocket連接,也就是說在處理websocket請求前,必需要處理一些http請求。
websocket到現在為止,已經有多個版本,netty有相應的對應類,這部分處理一般不需要人工干預。
如果運行正常的話,會在頁面的文本框中顯示1-20記數。
可以通過firefox或chrome的開發人員工具,顯看瀏覽器與服務器的交互。
主要是HttpServerChannelHandler2,加了些注釋和少量debug代碼。
package org.sl.demo.httpserver1;
import java.util.List;
import java.util.Map;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame;
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;
public class HttpServerChannelHandler2 extends SimpleChannelHandler{
public static boolean debug = true;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
Object msg = e.getMessage();
if(debug){
System.out.println("---------------");
System.out.println("message: "+msg.getClass());
}
//雖然是websocket,但在建立websocket連接前,先進行http握手,所以,這時也要處理http請求
//在http握手完成后,才是websocket下的通信
if(msg instanceof HttpRequest){
processHttpRequest(ch, (HttpRequest)msg);
}else if(msg instanceof WebSocketFrame){
processWebsocketRequest(ch,(WebSocketFrame)msg);
}else{
//未處理的請求類型
}
}
//這個方法:
//1.完成websocket前的http握手
//2.屏蔽掉非websocket握手請求
void processHttpRequest(Channel channel,HttpRequest request){
HttpHeaders headers = request.headers();
if(debug){
List<Map.Entry<String,String>> ls = headers.entries();
for(Map.Entry<String,String> i: ls){
System.out.println("header "+i.getKey()+":"+i.getValue());
}
}
//屏蔽掉非websocket握手請求
//只接受http GET和headers['Upgrade']為'websocket'的http請求
if(!HttpMethod.GET.equals(request.getMethod())
|| !"websocket".equalsIgnoreCase(headers.get("Upgrade"))){
DefaultHttpResponse resp = new DefaultHttpResponse(
HttpVersion.HTTP_1_1,
HttpResponseStatus.BAD_REQUEST);
channel.write(resp);
channel.close();
return;
}
WebSocketServerHandshakerFactory wsShakerFactory = new WebSocketServerHandshakerFactory(
"ws://"+request.headers().get(HttpHeaders.Names.HOST),
null,false );
WebSocketServerHandshaker wsShakerHandler = wsShakerFactory.newHandshaker(request);
if(null==wsShakerHandler){
//無法處理的websocket版本
wsShakerFactory.sendUnsupportedWebSocketVersionResponse(channel);
}else{
//向客戶端發送websocket握手,完成握手
//客戶端收到的狀態是101 sitching protocol
wsShakerHandler.handshake(channel, request);
}
}
//websocket通信
void processWebsocketRequest(Channel channel, WebSocketFrame request){
if(request instanceof CloseWebSocketFrame){
channel.close();
}else if(request instanceof PingWebSocketFrame){
channel.write(new PongWebSocketFrame(request.getBinaryData()));
}else if(request instanceof TextWebSocketFrame){
//這個地方 可以根據需求,加上一些業務邏輯
TextWebSocketFrame txtReq = (TextWebSocketFrame) request;
if(debug){ System.out.println("txtReq:"+txtReq.getText());}
//向ws客戶端發送多個響應
for(int i=1; i<=20; i++){
channel.write(new TextWebSocketFrame(""+i));
try{Thread.sleep(300);}catch(Exception ex){}
}
}else{
//WebSocketFrame還有一些
}
}
}
其他類跟網上的差不多: http://blog.csdn.net/shagoo/article/details/8028813
package org.sl.demo.httpserver1;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class HttpServer implements Runnable{
int port = 80;
public HttpServer(int port){
this.port = port;
}
@Override
public void run() {
ServerBootstrap b = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
b.setPipelineFactory(new HttpServerChannelPipelineFactory());
b.setOption("child.tcpNoDelay", true);
b.setOption("child.keepAlive", true);
b.bind(new InetSocketAddress(port));
}
public static void main(String[] args){
new HttpServer(80).run();
}
}
package org.sl.demo.httpserver1;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.codec.http.websocketx.WebSocket00FrameDecoder;
import org.jboss.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder;
public class HttpServerChannelPipelineFactory implements ChannelPipelineFactory {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline cp = Channels.pipeline();
cp.addLast("decoder", new HttpRequestDecoder());
// cp.addLast("decoder", new WebSocket00FrameDecoder());
cp.addLast("encoder", new HttpResponseEncoder());
// cp.addLast("downhandler", new HttpServerDownstreamHandler());
// cp.addLast("uphandler", new HttpServerUpstreamHandler());
cp.addLast("handler", new HttpServerChannelHandler2());
return cp;
}
}
測試頁面:
<html>
<head>
<script >
function connect1(){
alert('connect1');
var ta = document.getElementById('responseText');
var socket = new WebSocket('ws://127.0.0.1/websocket');
if (window.WebSocket) {
}else{
alert('Your browser does not support Web Socket.');
return;
}
socket.onopen = function(event) {
ta.value = "Web Socket opened!";
}
socket.onmessage = function(event) {
ta.value = event.data;
};
socket.onclose = function(event) {
ta.value = "Web Socket closed";
};
}
function connect() {
alert('connect');
var socket;
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if (window.WebSocket) {
socket = new WebSocket("ws://127.0.0.1/websocket");
socket.onmessage = function(event) {
var ta = document.getElementById('responseText');
ta.value = event.data;
};
socket.onopen = function(event) {
var ta = document.getElementById('responseText');
ta.value = "Web Socket opened!";
socket.send('hello');
};
socket.onclose = function(event) {
var ta = document.getElementById('responseText');
ta.value = "Web Socket closed";
};
socket.onerror = function(event){
};
} else {
alert("Your browser does not support Web Socket.");
}
}
</script>
</head>
<body>
<input type="button" onclick="connect1()" value="ws connect1"/> <br/><br/>
<input type="button" onclick="connect()" value="ws connect"/> <br/><br/>
<input id="responseText" type="text" value="123456"/>
</body>
</html>
來自:http://my.oschina.net/tangcoffee/blog/338562
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!