商业网站的域名代码,html网页模板大全,开发app需要的技术,腾讯企业邮箱经销商1、关于Netty
Netty 是一个利用 Java 的高级网络的能力#xff0c;隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
2、Maven依赖
dependencies!-- https://mvnrepository.com/artifact/io.netty/netty-all --dependencygr…1、关于Netty
Netty 是一个利用 Java 的高级网络的能力隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
2、Maven依赖
dependencies!-- https://mvnrepository.com/artifact/io.netty/netty-all --dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.36.Final/version/dependency
/dependencies3、SpringBootApplication
启动器中需要new一个NettyServer并显式调用启动netty。
SpringBootApplication
public class SpringCloudStudyDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudStudyDemoApplication.class,args);try {new NettyServer(12345).start();System.out.println(https://blog.csdn.net/moshowgame);System.out.println(http://127.0.0.1:6688/netty-websocket/index);}catch(Exception e) {System.out.println(NettyServerError:e.getMessage());}}
}4、NettyServer
启动的NettyServer这里进行配置
/*** NettyServer Netty服务器配置*/
public class NettyServer {private final int port;public NettyServer(int port) {this.port port;}public void start() throws Exception {EventLoopGroup bossGroup new NioEventLoopGroup();EventLoopGroup group new NioEventLoopGroup();try {ServerBootstrap sb new ServerBootstrap();sb.option(ChannelOption.SO_BACKLOG, 1024);sb.group(group, bossGroup) // 绑定线程池.channel(NioServerSocketChannel.class) // 指定使用的channel.localAddress(this.port)// 绑定监听端口.childHandler(new ChannelInitializerSocketChannel() { // 绑定客户端连接时候触发操作Overrideprotected void initChannel(SocketChannel ch) throws Exception {System.out.println(收到新连接);//websocket协议本身是基于http协议的所以这边也要使用http解编码器ch.pipeline().addLast(new HttpServerCodec());//以块的方式来写的处理器ch.pipeline().addLast(new ChunkedWriteHandler());ch.pipeline().addLast(new HttpObjectAggregator(8192));ch.pipeline().addLast(new WebSocketServerProtocolHandler(/ws, null, true, 65536 * 10));ch.pipeline().addLast(new MyWebSocketHandler());}});ChannelFuture cf sb.bind().sync(); // 服务器异步创建绑定System.out.println(NettyServer.class 启动正在监听 cf.channel().localAddress());cf.channel().closeFuture().sync(); // 关闭服务器通道} finally {group.shutdownGracefully().sync(); // 释放线程池资源bossGroup.shutdownGracefully().sync();}}
}5、MyChannelHandlerPool
通道组池管理所有websocket连接
/*** MyChannelHandlerPool* 通道组池管理所有websocket连接*/
public class MyChannelHandlerPool {public MyChannelHandlerPool(){}public static ChannelGroup channelGroup new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
}6、MyWebSocketHandler
处理ws一下几种情况
channelActive与客户端建立连接 channelInactive与客户端断开连接 channelRead0客户端发送消息处理
/*** NettyServer Netty服务器配置*/
public class NettyServer {private final int port;public NettyServer(int port) {this.port port;}public void start() throws Exception {EventLoopGroup bossGroup new NioEventLoopGroup();EventLoopGroup group new NioEventLoopGroup();try {ServerBootstrap sb new ServerBootstrap();sb.option(ChannelOption.SO_BACKLOG, 1024);sb.group(group, bossGroup) // 绑定线程池.channel(NioServerSocketChannel.class) // 指定使用的channel.localAddress(this.port)// 绑定监听端口.childHandler(new ChannelInitializerSocketChannel() { // 绑定客户端连接时候触发操作Overrideprotected void initChannel(SocketChannel ch) throws Exception {System.out.println(收到新连接);//websocket协议本身是基于http协议的所以这边也要使用http解编码器ch.pipeline().addLast(new HttpServerCodec());//以块的方式来写的处理器ch.pipeline().addLast(new ChunkedWriteHandler());ch.pipeline().addLast(new HttpObjectAggregator(8192));ch.pipeline().addLast(new WebSocketServerProtocolHandler(/ws, WebSocket, true, 65536 * 10));ch.pipeline().addLast(new MyWebSocketHandler());}});ChannelFuture cf sb.bind().sync(); // 服务器异步创建绑定System.out.println(NettyServer.class 启动正在监听 cf.channel().localAddress());cf.channel().closeFuture().sync(); // 关闭服务器通道} finally {group.shutdownGracefully().sync(); // 释放线程池资源bossGroup.shutdownGracefully().sync();}}
}7、socket.html
主要是连接ws发送消息以及消息反馈
!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd
html xmlnshttp://www.w3.org/1999/xhtml
headmeta http-equivContent-Type contenttext/html; charsetutf-8 /titleNetty-Websocket/titlescript typetext/javascript// by zhengkai.blog.csdn.netvar socket;if(!window.WebSocket){window.WebSocket window.MozWebSocket;}if(window.WebSocket){socket new WebSocket(ws://127.0.0.1:12345/ws);socket.onmessage function(event){var ta document.getElementById(responseText);ta.value event.data\r\n;};socket.onopen function(event){var ta document.getElementById(responseText);ta.value Netty-WebSocket服务器。。。。。。连接 \r\n;};socket.onclose function(event){var ta document.getElementById(responseText);ta.value Netty-WebSocket服务器。。。。。。关闭 \r\n;};}else{alert(您的浏览器不支持WebSocket协议);}function send(message){if(!window.WebSocket){return;}if(socket.readyState WebSocket.OPEN){socket.send(message);}else{alert(WebSocket 连接没有建立成功);}}/script
/head
body
form onSubmitreturn false;labelID/labelinput typetext nameuid value${uid!!} / br /labelTEXT/labelinput typetext namemessage value这里输入消息 / br /br / input typebutton value发送ws消息onClicksend(this.form.uid.value:this.form.message.value) /hr colorblack /h3服务端返回的应答消息/h3textarea idresponseText stylewidth: 1024px;height: 300px;/textarea
/form
/body
/html8、Controller
写好了html当然还需要一个controller来引导页面。
RestController
public class IndexController {GetMapping(/index)public ModelAndView index(){ModelAndView mavnew ModelAndView(socket);mav.addObject(uid, RandomUtil.randomNumbers(6));return mav;}
}9、改造netty支持url参数
1.首先调整一下加载handler的顺序优先MyWebSocketHandler在WebSocketServerProtocolHandler之上。
ch.pipeline().addLast(new MyWebSocketHandler());
ch.pipeline().addLast(new WebSocketServerProtocolHandler(/ws, null, true, 65536 * 10));2.其次改造MyWebSocketHandler 的channelRead方法首次连接会是一个FullHttpRequest类型可以通过FullHttpRequest.uri()获取完整ws的URL地址之后接受信息的话会是一个TextWebSocketFrame类型。
public class MyWebSocketHandler extends SimpleChannelInboundHandlerTextWebSocketFrame {Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(与客户端建立连接通道开启);//添加到channelGroup通道组MyChannelHandlerPool.channelGroup.add(ctx.channel());}Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {System.out.println(与客户端断开连接通道关闭);//添加到channelGroup 通道组MyChannelHandlerPool.channelGroup.remove(ctx.channel());}Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//首次连接是FullHttpRequest处理参数 by zhengkai.blog.csdn.netif (null ! msg msg instanceof FullHttpRequest) {FullHttpRequest request (FullHttpRequest) msg;String uri request.uri();Map paramMapgetUrlParams(uri);System.out.println(接收到的参数是JSON.toJSONString(paramMap));//如果url包含参数需要处理if(uri.contains(?)){String newUriuri.substring(0,uri.indexOf(?));System.out.println(newUri);request.setUri(newUri);}}else if(msg instanceof TextWebSocketFrame){//正常的TEXT消息类型TextWebSocketFrame frame(TextWebSocketFrame)msg;System.out.println(客户端收到服务器数据 frame.text());sendAllMessage(frame.text());}super.channelRead(ctx, msg);}Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {}private void sendAllMessage(String message){//收到信息后群发给所有channelMyChannelHandlerPool.channelGroup.writeAndFlush( new TextWebSocketFrame(message));}private static Map getUrlParams(String url){MapString,String map new HashMap();url url.replace(?,;);if (!url.contains(;)){return map;}if (url.split(;).length 0){String[] arr url.split(;)[1].split();for (String s : arr){String key s.split()[0];String value s.split()[1];map.put(key,value);}return map;}else{return map;}}
}3.html中的ws地址也进行改造
socket new WebSocket(ws://127.0.0.1:12345/ws?uid666gid777);4.改造后控制台输出情况
收到新连接
与客户端建立连接通道开启
接收到的参数是{uid:666,gid:777}
/ws
客户端收到服务器数据142531:这里输入消息
客户端收到服务器数据142531:这里输入消息
客户端收到服务器数据142531:这里输入消息failed: WebSocket opening handshake timed out