we can use netty to build a chatroom using its websocket.
First, we can use SSL to make it security.
SSLContext context = BogusSslContextFactory.getServerContext();
SSLEngine engine = context.createSSLEngine();
engine.setUseClientMode(false);
ch.pipeline().addFirst(new SslHandler(engine));
ch means ours Channel
and we must set a ChannelGroup in order to make a chat room , as chat room means many client,
and only a channel cann't satify.
private final ChannelGroup channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
and in the method initChannel of our ChannelInitializer, we can make like this
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(64 * 1024));
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpRequestHandler("/ws"));
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast(new TextWebSocketFrameHandler(group));
}
and the last line, the parameter group means channelGroup we passed to it.
As we all know, when we use web socket, we much first use http ,and then upgrade it , and the line which stay third from the last
handle our http request
In this handler, we can get the our runtime path like this
URL location = HttpRequestHandler.class.getProtectionDomain().getCodeSource().getLocation();
in fact , if we use eclipse locally, it means the path of class under target file, not incluing package.
and this HttpRequestHandler use "/ws" as parameter because we expect only handler the url with the
suffixes "/ws", and in the handler , we can make a judgment like this
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
if (wsUri.equalsIgnoreCase(request.getUri())) {
ctx.fireChannelRead(request.retain());
} else {
.....
}
reuqest.getUri() can get the suffixes of url request , and if it's "/ws", fire next channelHandler.
and in our TextWebSocketFrameHandler we can code like this
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
ctx.pipeline().remove(HttpRequestHandler.class);
group.writeAndFlush(new TextWebSocketFrame("Client " + ctx.channel() + " joined"), new ChannelMatcher() {
@Override
public boolean matches(Channel channel) {
return true;
}
});
group.add(ctx.channel());
} else {
super.userEventTriggered(ctx, evt);
}
}
@Override
public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
group.writeAndFlush(msg.retain(), new ChannelMatcher() {
public boolean matches(Channel channel) {
return true;
}
});
}
and every time a client join, we add it to our channel group , and then when any client type works, we use group
writeAndFlush to made it seen by all!