思路
利用WebSocketServerProtocolHandler 进行实现 其原理是利用101状态码讲http协议转换为websocket协议
服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| package com.jhj.netty.websocket;
import com.jhj.netty.heartbeat.MyServerHandler; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
public class MyServer { public static void main(String[] args) throws Exception{ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup();
try{ ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() {
@Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator(8192));
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
pipeline.addLast(new MyTextWebSocketFrameHandler()); } });
ChannelFuture channelFuture = serverBootstrap.bind(7000).sync(); channelFuture.channel().closeFuture().sync();
}finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
|
服务端Handler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package com.jhj.netty.websocket;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.time.LocalDate; import java.time.LocalDateTime;
public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { System.out.println("handlerAdded 被调用"+ctx.channel().id().asLongText()); }
@Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { System.out.println("handlerRemoved 被调用"+ctx.channel().id().asLongText()); }
@Override protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { System.out.println("服务器收到消息"+msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间"+ LocalDateTime.now()+msg.text())); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("异常发生"+cause.getMessage()); ctx.close(); } }
|
Html页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> var socket; if (window.WebSocket){ socket = new WebSocket("ws://localhost:7000/hello");
socket.onmessage=function (ev){ let rt = document.getElementById("responseText"); rt.value=rt.value+"\n"+ev.data; }
socket.onopen=function (ev){ let rt = document.getElementById("responseText"); rt.value="连接开启"; }
socket.onclose=function (ev){ let rt = document.getElementById("responseText"); rt.value=rt.value+"\n"+"连接关闭"; } }else{ alert("当前浏览器不支持websocket") }
function send(message){ if (!window.socket){
return; }
if (socket.readyState == WebSocket.OPEN){ socket.send(message); }else { alert("连接没有开启") }
} </script> <form onsubmit="return false"> <textarea name="message" style="height: 300px;width: 300px"></textarea> <input type="button" value="发生消息" onclick="send(this.form.message.value)"></input> <textarea id="responseText" style="height: 300px;width: 300px"></textarea> <input type="button" value="清空消息" onclick="document.getElementById('responseText').value=''"></input> </form> </body> </html>
|
作者声明