NIO框架Netty+WebSocket实现网页聊天

前言

Netty是又JBOOS提供的一个java开源框架,是一个基于NIO的客户服务器端编程框架。优势:
1、netty提供简易的API。
2、基于事件驱动的编程方式来编程网络通讯程序。
3、更高的吞吐量。
4、多种编解码功能,支持多种主流协议。

那么今天就基于netty+websocket实现简易的网页聊天的Demo。

一、引入pom文件依赖。
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.36.Final</version>
</dependency>
二、主方法

里面首先创建两个线程,主线程池和从线程池。然后创建Netty服务启动对象serverBootstrap。很多都是固定配置,把两个线程加载到group里,然后指定通道类型,初始化加载channel。并且定义端口号。

public class WebSocketNettyService {
    public static void main(String[] args) {
        NioEventLoopGroup mainGrp = new NioEventLoopGroup();    //主线程池
        NioEventLoopGroup minorGrp = new NioEventLoopGroup();     //从线程池
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap(); //创建Netty服务器启动对象
            serverBootstrap
                    .group(mainGrp, minorGrp)  //指定上面创建的两个线程池
                    .channel(NioServerSocketChannel.class)   //指定通道类型
                    .childHandler(new WebSocketChannelInitializer());  //指定初始化器用来加载Channel收到事件消息

            
            ChannelFuture future = serverBootstrap.bind(8095).sync();   //服务器绑定端口,启动服务,同步

            future.channel().closeFuture().sync(); //等待服务器关闭
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mainGrp.shutdownGracefully();
            minorGrp.shutdownGracefully();
        }
    }
}
三、通道初始化器

通道初始化器,用来加载通道通道处理器,在这个方法加载对应的ChannelHandler。

public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast(new HttpServerCodec());    //添加一个http的编解码器
        pipeline.addLast(new ChunkedWriteHandler());    //添加一个大数据流的支持
        pipeline.addLast(new HttpObjectAggregator(1024 * 64)); //添加一个聚合器,主要将HTTPMessage聚合成FullhttpRequest/Response
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); //需求接收请求的路由,必须使用以ws结尾的请求才能进入
        pipeline.addLast(new ChatHandler());//自定义Handler

    }

    public void handlerAdded(ChannelHandlerContext channelHandlerContext) throws Exception {
    }

    public void handlerRemoved(ChannelHandlerContext channelHandlerContext) throws Exception {
    }

    public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) throws Exception {
    }
}
四、自定义的Handler方法

这里首先定义一个静态变量clients,用来保存所有的客户端连接。里面的channelRead0方法是当Channel有新的事件消息会自动调用, 而handlerAdded方法则是当有新的客户端连接服务器会自动调用这个方法。

public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:MM");

    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame mgs) throws Exception {
        String text = mgs.text();   //获取客户端发送过来的文本消息
        System.out.println("接收到的消息:" + text);
        for(Channel client: clients){
            client.writeAndFlush(new TextWebSocketFrame(sdf.format(new Date())+":"+text)); //将消息发送给所有客户端
        }
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        clients.add(ctx.channel());
    }
}
五、前端页面
前端页面比较简单,就是建立连接,发送消息和接收消息等。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="text" id="send_message">
<input type="button" value="发送消息" onclick="sendMessage()">

接收到的消息:
<p id="accept_message" style="background-color:#AAAAAS"></p>

<script>
    var websocket = null;
    if (window.WebSocket) { //判断当前浏览器是否支持websocket
        websocket = new WebSocket("ws://127.0.0.1:9090/ws");
        websocket.onopen = function () {
            console.log("建立连接");
        }
        websocket.close = function () {
            console.log("断开连接");
        }
        websocket.onmessage = function (e) {
            console.log("接收到服务器的消息:" + e.data)
            var accept_message = document.getElementById("accept_message");
            accept_message.innerHTML += e.data + "<br/>";
        }
    } else {
        alert("当前浏览器不支持websocket");
    }

    function sendMessage() {
        var send_message = document.getElementById("send_message");
        websocket.send(send_message.value);
    }

</script>
</body>
</html>

最后运行演示如图:
运行演示图

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值