Netty4 + WebSocket 实现网页版聊天室

网页聊天室效果展示:

 

 

① Netty依赖


	io.netty
	netty-all
	4.1.32.Final

 

② Netty的服务端:定义NettyServer,让其支持Websocket通信,并添加自己的请求处理器

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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;

public class NettyServer {

	private int port;

	public NettyServer(int port) {
		this.port = port;
	}

	public void start() {

		// 创建服务类
		ServerBootstrap sb = new ServerBootstrap();

		// 创建boss和woker
		NioEventLoopGroup boss = new NioEventLoopGroup();
		NioEventLoopGroup woker = new NioEventLoopGroup();

		try {
			// 设置线程池
			sb.group(boss, woker);

			// 设置channel工厂
			sb.channel(NioServerSocketChannel.class);

			// 设置管道
			sb.childHandler(new ChannelInitializer() {
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					
					ch.pipeline().addLast(new HttpServerCodec());// websocket基于http协议,需要HttpServerCodec
					ch.pipeline().addLast(new HttpObjectAggregator(65535)); // http消息组装
					ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws")); // websocket通信支持
					ch.pipeline().addLast(new MyServerHandler()); // 自定义处理器
					
				}
			});

			// 服务器异步创建绑定
			ChannelFuture cf = sb.bind(port).sync();

			// 等待服务端关闭
			cf.channel().closeFuture().sync();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			boss.shutdownGracefully();
			woker.shutdownGracefully();
		}
	}

	/**
	 * server启动
	 * @param args
	 */
	public static void main(String[] args) {
		new NettyServer(1234).start();
	}
}

③ 自定义监听Channel的处理器

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.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

public class MyServerHandler extends
		SimpleChannelInboundHandler {

	public static ChannelGroup channels = new DefaultChannelGroup(
			GlobalEventExecutor.INSTANCE);

	/**
	 * 监听客户端注册
	 */
	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		// 新客户端连接,通知其他客户端
		for (Channel channel : channels) {
			String msg = "~~用户"
					+ ctx.channel().remoteAddress() + "上线~~";
			channel.writeAndFlush(msgPot(msg));
		}
		// 加入队列
		channels.add(ctx.channel());
	}

	/**
	 * 监听客户端断开
	 */
	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		// 离开时,通知其他客户端
		for (Channel channel : channels) {
			if (channel != ctx.channel()) {
				String msg = "~~用户"
						+ ctx.channel().remoteAddress() + "离开~~";
				channel.writeAndFlush(msgPot(msg));
			}
		}
		// 整理队列
		channels.remove(ctx.channel());
	}

	/**
	 * 读取客户端发过来的消息
	 */
	@Override
	public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame tmsg)
			throws Exception {
		// 处理消息
		for (Channel channel : channels) {
			// 判断是否是当前用户的消息
			if (channel != ctx.channel()) {
				String msg = "[用户" + channel.remoteAddress() + " 说:]"
						+ tmsg.text();
				channel.writeAndFlush(msgPot(msg));
			} else {
				String msg = "[我说:]" + tmsg.text();
				channel.writeAndFlush(msgPot(msg));
			}
		}
	}

	/**
	 * 监听连接异常
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		ctx.close(); // 关闭
	}

	/**
	 * 封装消息
	 * 
	 * @param msg
	 * @return
	 */
	public TextWebSocketFrame msgPot(String msg) {
		return new TextWebSocketFrame(msg);
	}

}

 

至此,服务端的代码就已经结束了,下面开始书写页面客户端代码

 

④ netty.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>




netty聊天室






	
Netty4+Websocket聊天室

 

tip:web项目和Netty服务的启动问题

① 先执行NettyServer的main方法,开启NettyServer。然后tomcat启动web项目,访问netty.jsp。

② web项目中启动时创建一个线程去启动Netty服务,访问netty.jsp

 

参考博客:https://www.jianshu.com/p/0b2772f5778c

你可能感兴趣的:(netty)