Netty实现WebSocket通信案例
2019/11/20 11:50 分类: 技术交流 浏览:1
功能介绍
- Netty开发服务端HTML实现客户端
- 实现服务端与客户端时实时交互
1 、导包
2 、工程配置文件:NettyConfig
3、MyWebSocketHandler
public class MyWebSocketHandler extends SimpleChannelInboundHandler<Object> { private WebSocketServerHandshaker handshaker;
//请求路径
private static final String WEB_SOCKET_URL = "ws://localhost:8888/websocket";
//工程出现异常的时候调用@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace(); ctx.close(); //关闭当前连接
}
//客户端与服务器创建连接的时候调用@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.add(ctx.channel());
System.out.println("客户端与服务器连接开启");
}
//客户端与服务器断开连接的时候调用@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.remove(ctx.channel());
System.out.println("客户端与服务器断开连接");
}
//服务端接收客户端发送过来的数据结束之后调用@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); //进行数据清除
}
//服务端处理客户端调用的核心方法
protected void messageReceived(ChannelHandlerContext context, Object msg) throws Exception {
//处理客户端向服务端发起http握手请求业务if(msg instanceof FullHttpRequest){
handHttpRequest(context,(FullHttpRequest) msg);
}else if(msg instanceof WebSocketFrame){
//处理websocket连接业务handWebSocketFrme(context,(WebSocketFrame)msg);
}
}
/**
- 处理客户端与服务端之前的websocket业务
- @param ctx
- @param frame
*/
private void handWebSocketFrme(ChannelHandlerContext ctx,WebSocketFrame frame){
//判断是否是关闭websocket的指令
if(frame instanceof CloseWebSocketFrame){ handshaker.close(ctx.channel(),((CloseWebSocketFrame) frame).retain());
}
//判断是否是Ping消息
if(frame instanceof PingWebSocketFrame){
//返回一个胖信息
ctx.channel().write(new PongWebSocketFrame(frame.content().retain())); return;
}
//判断是否是二进制消息,如果是二进制消息,抛出异常if(!(frame instanceof TextWebSocketFrame)){
System.out.println("目前我们不支持二进制消息");
throw new RuntimeException(this.getClass().getName()+"不支持的消息");
}
//返回应答消息
//获取客户端向服务端发送的消息
String request = ((TextWebSocketFrame)frame).text(); System.out.println("服务端收到客户端的消息===>"+request); TextWebSocketFrame tws = new TextWebSocketFrame(new
Date().toString()+ctx.channel().id()+"===>"+request);
//群发,服务端向每个上来的客户端群发消息NettyConfig.group.writeAndFlush(tws);
}
/**
- 处理客户端向服务器发起http握手请求的业务
- @param ctx
- @param req
*/
private void handHttpRequest(ChannelHandlerContext ctx,FullHttpRequest req){
// req.headers().get()
// req.decoderResult().isSuccess()
//不是websocket,就不是客户端发给服务器的Http请求if(!req.decoderResult().isSuccess()|| !
("websocket").equals(req.headers().get("Upgrade"))){
sendHttpResponse(ctx,req,new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
return;
}
WebSocketServerHandshakerFactory wsFactory =
new WebSocketServerHandshakerFactory(WEB_SOCKET_URL,null,false); handshaker = wsFactory.newHandshaker(req);
if(handshaker==null){
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
}else{
handshaker.handshake(ctx.channel(),req);
}
}
/**
- 服务端向客户端响应消息
- @param ctx
- @param req
- @param res
4、初始化连接各个组件:MyWebSocketChannelHandler
/**
* 初始化连接各个组件
*/
public class MyWebSocketChannelHandler extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel e) throws Exception { e.pipeline().addLast("http‐codec",new HttpServerCodec()); e.pipeline().addLast("aggregator",new HttpObjectAggregator(66636)); e.pipeline().addLast("http‐chunked",new ChunkedWriteHandler()); e.pipeline().addLast("handler",new MyWebSocketHandler());
}
}
5 、程序入口
/**
* 程序的入口,负责启动应用
*/
public class Main {
public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try {
ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workGroup); b.channel(NioServerSocketChannel.class); b.childHandler(new MyWebSocketChannelHandler());
System.out.println("服务端开启等待客户端连接");
Channel ch = b.bind(8888).sync().channel();
} catch (Exception e) {
e.printStackTrace();
} finally {
//优雅的退出程序bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();
}
}
}
6 、web端测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF‐8">
<title>WebSocket客户端</title>
</head>
<script>
var socket; if(!window.WebSocket){
window.WebSocket = window.MozWebSocket;
}
if(window.WebSocket){
socket = new WebSocket("ws://localhost:8888/websocket"); socket.onmessage = function (event) {
var ta = document.getElementById("responseContext"); ta.value += event.data +"\r\n";
}
socket.onopen = function (event) {
var ta = document.getElementById("responseContext"); ta.value = "您浏览器支持webSoceket,请进行后续 操作\r\n";
}
socket.onclose = function (event) {
var ta = document.getElementById("responseContext"); ta.value = "";
ta.value = "webSoceket连接已经关闭";
}
}else{
console.debug("浏览器不支持webSocket")
}
function send() {
var message = document.getElementById("message").value; if(!window.WebSocket){
return;
}
if(socket.readyState == WebSocket.OPEN){ socket.send(message)
}else{
alert("连接没有建立成功!");
}
}
</script>
赞 0