Netty-WebSocket 网络聊天demo教程

2021-12-22 15:41:36 浏览数 (1)

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

代码语言:javascript复制
<!--先来一下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服务器基础配置
代码语言:javascript复制
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服务器初始化配置
代码语言:javascript复制
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 服务器业务处理
代码语言:javascript复制
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级别,主要大家可以简单清晰的看出来数据的传输和响应

代码语言:javascript复制
<!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>

0 人点赞