今天学习了netty打算写一个小的测试程序,来练习一下怎么使用
首先我们打算写的是一个基于web的聊天室小程序让我们梳理一下
首先我们编写一个启动器这里我们采用的是主从多线程reactor模型
public class WebSocketServer{
public static void main(String[] args) throws InterruptedException {
EventLoopGroup mainGroup = new NioEventLoopGroup();
EventLoopGroup subGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(mainGroup,subGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WSServerIniterlize());
ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
channelFuture.channel().closeFuture().sync();
} finally {
mainGroup.shutdownGracefully();
subGroup.shutdownGracefully();
}
}
}
这里我们的想法是通过websocket进行通信我们想实现的是聊天室的功能想要实现一种实时通讯的功能我们选择websocket这种方法而不是Ajax轮询。后一种那个方法是不停的从客户端向服务器发起询问这样有损性能。
public class WSServerIniterlize extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//加入http协议编解码器
pipeline.addLast("HttpServerCodec",new HttpServerCodec());
//大数据流的处理器
pipeline.addLast(new ChunkedWriteHandler());
//http聚合器对HTTPmessage进行聚合聚合为FULLHTTPREAUEST/REPONSE
// 基本在netty的编程中都会使用到这个
pipeline.addLast(new HttpObjectAggregator(1024*64));
// =================以上是HTTP协议的支持===========
//针对websocket处理的的协议,用与指定给客户端连接访问的路由
//会帮你处理一些握手动作(close,ping,pong)等繁重且复杂的事
//对于websocket来讲都是以frames来传输的
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
//加入自定义助手类
pipeline.addLast(new ChatHandler());
}
}
自定义处理器
package com.caohao.weichat.webSocket;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.time.LocalDateTime;
/**
* 处理消息的handler
* TextWebSocketFrame:用于为websocket专门处理文本的对象frame是消息的载体
*/
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
//记录所有客户端的channel
private static ChannelGroup usersChannel = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame message) throws Exception {
String text = message.text();
System.out.println("接收到的消息"+text);
Channel channel = channelHandlerContext.channel();
// for (Channel channel1:usersChannel){
// channel1.writeAndFlush(new TextWebSocketFrame("[服务器接收到消息:]"+ LocalDateTime.now()
// +"消息为:"+text));
// }
usersChannel.writeAndFlush(new TextWebSocketFrame("[服务器接收到消息:]"+ LocalDateTime.now()
+"消息为:"+text));
}
/**
* 当客户端打开链接就将这个channel放入管理
* @param ctx
* @throws Exception
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
usersChannel.add(channel);
}
/**
* 关闭浏览器时移除相应的channel
* @param ctx
* @throws Exception
*/
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
//这句话不写也自动移除
//usersChannel.remove(ctx.channel());
System.out.println("移除了id为"+ctx.channel().id().asShortText()+"channel");
}
}
页面代码
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div>发送消息:</div> <input type="text" id="msgContent"> <input type="button" value="点击发送" onclick="CHAT.chat()">
<div>接收消息:</div> <div id="receiveMsg" style="background-color: gainsboro;"> </div>
<script type="application/javascript"> window.CHAT = { socket:null, init:function(){ if(window.WebSocket){ CHAT.socket = new WebSocket("ws://127.0.0.1:8080/ws"); CHAT.socket.onopen = function(){ console.log("连接建立成功"); }, CHAT.socket.onmessage = function(e){ console.log("接收到消息"+e.data); var receiveMsg = document.getElementById("receiveMsg"); var html = receiveMsg.innerHTML; receiveMsg.innerHTML = html + "<br/>" + e.data; }, CHAT.socket.onerror = function(){ console.log("连接发生错误"); }, CHAT.socket.onclose = function(){ console.log("连接关闭成功"); } } else{ alert("浏览器不支持websocket协议"); }; }, chat: function(){ var msg = document.getElementById("msgContent"); CHAT.socket.send(msg.value); } } CHAT.init(); </script></body></html>