Websocket:
Websocket是HTML5新增加的协议,在服务器与浏览器之间建立一个不受限的双向通道,可以实现服务器主动向浏览器推送消息。
Websocket是利用Http协议来实现的。webscoket连接是都是通过浏览器发起的。他的建立连接请求是一个http请求。
请求格式如下:
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket //表明这个连接将要被转为websocket连接
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string //用来标识连接
Sec-WebSocket-Version: 13
服务器响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string
响应码101代表协议即将转化。那么我们传递参数也就是通过这一次http建立连接。
我们在建立连接时候将请求截下来,然后拿掉参数,再把它的拿出来,从新封装url。
我们在pipeline添加如下handler
ch.pipeline().addLast("http-decoder", new HttpServerCodec());
// 加入ObjectAggregator解码器,作用是他会把多个消息转换为单一的FullHttpRequest或者FullHttpResponse
ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(65536));
// 加入chunked 主要作用是支持异步发送的码流(大文件传输),但不专用过多的内存,防止java内存溢出
ch.pipeline().addLast(new ChunkedWriteHandler());
// 加入自定义handler
ch.pipeline().addLast( handler);
// 加入webSocket的hanlder
ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws"));
顺序不能错,亲身实践,代码玄学(其实是自己学的不到位)
然后在自己的handler里边重写read方法(注意是read不是read0)
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (null != msg && msg instanceof FullHttpRequest) {
logger.info("准备提取token");
//转化为http请求
FullHttpRequest request = (FullHttpRequest) msg;
//拿到请求地址
String uri = request.uri();
//判断是不是websocket请求,如果是拿出我们传递的参数(我的是token)
String origin = request.headers().get("Origin");
if (null == origin) {
ctx.close();
} else {
if (null != uri && uri.contains("/ws") && uri.contains("?")) {
String[] uriArray = uri.split("\\?");
if (null != uriArray && uriArray.length > 1) {
String[] paramsArray = uriArray[1].split("=");
if (null != paramsArray && paramsArray.length > 1) {
srctoken = paramsArray[1];
logger.info("提取token成功");
}
}
//重新设置请求地址
request.setUri("/ws");
}
}
}
//接着建立请求
super.channelRead(ctx, msg);
}
其实这个步骤是,在建立连接的时候在中途给他截下来参数,然后把参数去掉接着执行。
前台代码:
window.CHAT = {
socket: null,
init: function() {
if (window.WebSocket) {
CHAT.socket = new WebSocket("ws://127.0.0.1:8888/ws?token=测试");
CHAT.socket.onopen = function(event) {
console.log("连接建立成功...");
};
CHAT.socket.onclose = function(event) {
console.log("连接关闭...");
};
CHAT.socket.onerror = function(event) {
console.log("发生错误...");
console.log(event);
};
CHAT.socket.onmessage = function(e) {
console.log("接收到消息" + e.data);
var receiveMsg = document.getElementById("receiveMsg");
var html = receiveMsg.innerHTML;
receiveMsg.innerHTML = html + "\n" + e.data;
};
} else {
alert("浏览器不支持websocket协议...");
}
},
chat: function() {
var msg = document.getElementById("msgContent");
CHAT.socket.send(msg.value);
}
};
CHAT.init();