美文网首页
Netty-WebSocket 网络聊天demo教程

Netty-WebSocket 网络聊天demo教程

作者: 名字是乱打的 | 来源:发表于2020-01-24 20:41 被阅读0次

    毕设需求,调研一下,新手来说任何项目都是从研究demo开始的(至少我这个菜鸡就这样,只能先研究研究再开始做自己的项目),这里提供了一个我最开始的demo,提供借鉴

    <!--先来一下netty的 maven仓库配置需求-->
     <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.25.Final</version>
            </dependency>
    

    服务端搭建

    服务器三个代码块基本是层层构建,像盖房子一样从低向上一样
    部分代码是常规配置,大家注意看注释哦

    1.1服务器基础配置
    package com.zyh.future.server;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    public class WebSocketNettyServer {
        public static void main(String[] args){  
            //创建netty的主从两个线程池
            NioEventLoopGroup mainGrp = new NioEventLoopGroup();//主线程池
            NioEventLoopGroup subGrp = new NioEventLoopGroup();//从线程池
    
            try {
                //创建Netty服务器启动对象
                ServerBootstrap serverBootstrap = new ServerBootstrap();
    
                //初始化服务器启动对象
                serverBootstrap
                        //为netty服务器指定和配备主从线程池
                        .group(mainGrp,subGrp)
                        //指定netty通道类型
                        .channel(NioServerSocketChannel.class)
                        //指定通道初始化器用来加载当channel收到消息后
                        //如何进行业务处理
                        .childHandler(new WebSocketChannelInitializer());
    
                //绑定服务器端口, 以同步的方式启动服务器
                ChannelFuture channelFuture = serverBootstrap.bind(9090).sync();
                //等待服务器关闭
                channelFuture.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //使用优雅的方式关闭服务器
                //主要是关闭两个线程池
                mainGrp.shutdownGracefully();
                subGrp.shutdownGracefully();
            }
    
    
        }
    }
    
    
    2.2服务器初始化配置
    package com.zyh.future.server;
    
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.handler.codec.http.HttpObjectAggregator;
    import io.netty.handler.codec.http.HttpServerCodec;
    import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
    import io.netty.handler.stream.ChunkedWriteHandler;
    
    /**
     * 功能描述: 通道初始化器器
     * 用来加载通道处理器(channelhandler)
     * @Author: Zyh
     * @Date: 2020/1/22 20:31
     */
    public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {
    
        @Override
        //初始化通道
        //在这个方法中加载对应的ChannelHandler
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            /* 固定写法部分*/
            //获取管道,将一个个ChannelHandler添加到管道中
            ChannelPipeline channelPipeline = socketChannel.pipeline();
            //可以将channelpipeline理解为拦截器
            //当我们的socketChannel数据进来时候会依次调用我们的ChannelHandler
    
            //添加一个http的编解码器
            channelPipeline.addLast(new HttpServerCodec());
            //添加大数据流支持
            channelPipeline.addLast(new ChunkedWriteHandler());
            //添加聚合器 ,可以将我们的httpmaessage聚合成Fullhttprequest/respond ---想拿到请求和响应就要添加聚合器
            channelPipeline.addLast(new HttpObjectAggregator(1024*24));//指定缓存大小
            /* 固定写法部分*/
    
            //指定接收请求的路由
            //指定必须使用ws为结尾的url才能访问
            channelPipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
    
            //添加自定义的handler进行业务处理
            channelPipeline.addLast(new ChatHandler());
    
    
        }
    }
    
    
    3.3 服务器业务处理
    package com.zyh.future.server;
    
    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;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    
    //extends SimpleChannelInboundHandler<TextWebSocketFrame> 使我们接收到的消息会封装到一个TextWebSocketFrame中
    public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
        //用来保存所有的客户端连接
        private static ChannelGroup clients=new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
        //创建一个时间生成器
        private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd hh:MM");
    
        @Override //该方面当接收到数据时候会自动调用
        protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
            String text=msg.text();
            System.out.println("接收到的消息为: "+text);
    
            //遍历clients(所有客户端,群发)
            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());//将新的连接加入channel中
        }
    }
    
    

    客户端搭建

    最简单的demo级别,主要大家可以简单清晰的看出来数据的传输和响应

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>在线聊天室</title>
    </head>
    <body>
        <input type="text" id="message">
        <input type="button" value="发送消息" onclick="sendMessage()">
        </br>
        接收到的消息为:
        </br>
        <p id="server_message" style="background-color: #aaaaaa"></p>
    
    
        <script>
        //判断当前浏览器是否支持websocket (H5才支持)
            var  websocket=null;
            if (window.WebSocket){
                websocket=new WebSocket("ws://127.0.0.1:9090/ws");//前面的ws是协议,后面的ws是我们指定了接收的为ws结尾的路由
                websocket.onopen=function () {
                    console.log("建立连接");
                }
                websocket.onclose=function () {
                    console.log("断开连接");
                }
                websocket.onmessage=function (e) {
                    console.log("接收到服务器的数据为: "+e.data);
                    var server_messsage=document.getElementById("server_message");
                    server_messsage.innerHTML+=e.data+"</br>";
                }
            }else {
                alert("当前浏览器不支持websocket");
            }
    
            function sendMessage() {
                var  message=document.getElementById("message");
                websocket.send(message.value);
            }
        </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:Netty-WebSocket 网络聊天demo教程

          本文链接:https://www.haomeiwen.com/subject/euhmzctx.html