SpringBoot+Netty实现CS交互(一)

添加依赖

 <dependency>
     <groupId>io.netty</groupId>
     <artifactId>netty-all</artifactId>
     <version>4.1.25.Final</version>
 </dependency>

ws服务端

package com.imooc.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/12/28 22:21
 */
public class WSServer
{
    public static void main(String[] args)
    {
        //主子线程组
        NioEventLoopGroup mainGroup = new NioEventLoopGroup();
        NioEventLoopGroup subGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = null;
        try
        {
            serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(mainGroup, subGroup)//设置主从线程组
                    .channel(NioServerSocketChannel.class)//设置nio双向通道
                    .childHandler(new WSServerInitializer());//子处理器,用于处理workerGroup
            ChannelFuture future = serverBootstrap.bind(8088).sync();
            //监听关闭的channel,设置为同步方式
            future.channel().closeFuture().sync();
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            //优雅关闭
            mainGroup.shutdownGracefully();
            subGroup.shutdownGracefully();
        }
    }
}

子处理器

package com.imooc.netty.websocket;

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.WebSocketClientProtocolHandler;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/12/28 22:37
 */
public class WSServerInitializer extends ChannelInitializer<SocketChannel>
{

    @Override
    protected void initChannel(SocketChannel ch) throws Exception
    {
        ChannelPipeline pipeline = ch.pipeline();
        //ws基于http协议,所以要有编解码器
        pipeline.addLast(new HttpServerCodec());
        //对写入大数据流的支持
        pipeline.addLast(new ChunkedWriteHandler());
        //在netty中,几乎都会使用到这个handler
        pipeline.addLast(new HttpObjectAggregator(1024 * 64));
        //服务器处理的协议,用户给客户端连接访问的路由
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        // 自定义的handler
        pipeline.addLast(new ChatHandler());
    }
}

该类继承ChannelInitializer,泛型为SocketChannel!通过获取的管道,使用addLast添加ws的基本配置。上面的代码就是基本配置!

自定义消息处理

package com.imooc.netty.websocket;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
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.EventExecutorGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.time.LocalDateTime;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/12/28 22:52
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>
{
    //用户记录和管理所有客户端的channel
    private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception
    {
        //获取客户端传输的消息
        String msgText = msg.text();
        System.out.println("接收到的数据: " + msgText);
//        for (Channel client : clients)
//        {
//            client.writeAndFlush(new TextWebSocketFrame("[服务器接收到的消息]"
//                    + LocalDateTime.now() + " 接收到的消息为: " + msgText));
//        }
        clients.writeAndFlush(new TextWebSocketFrame("[服务器接收到的消息]"
                + LocalDateTime.now() + " 接收到的消息为: " + msgText));
    }

    /**
     * @Description: 当客户端连接服务端之后, 获取到客户端的channel, 并且放到channelGroup中
     * @Param: ctx
     * @return:
     * @Author: 朝花不迟暮
     * @Date: 2020/12/28
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception
    {
        Channel channel = ctx.channel();
        clients.add(channel);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
    {
        System.out.println("长id: " + ctx.channel().id().asLongText());
        System.out.println("短id: " + ctx.channel().id().asShortText());
    }
}

前端页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title></title>
</head>
<body>

<div>发送消息:</div>
<input type="text" id="msgContent"/>
<input type="button" value="点我发送" onclick="CHAT.chat()"/>

<div>接受消息:</div>
<div id="receiveMsg" style="background-color: gainsboro;"></div>

<script type="application/javascript">

    window.CHAT = {
        socket: null,
        init: function () {
            if (window.WebSocket) {
                CHAT.socket = new WebSocket("ws://192.168.0.102:8088/ws");
                CHAT.socket.onopen = function () {
                    console.log("连接建立成功...");
                },
                    CHAT.socket.onclose = function () {
                        console.log("连接关闭...");
                    },
                    CHAT.socket.onerror = function () {
                        console.log("发生错误...");
                    },
                    CHAT.socket.onmessage = function (e) {
                        console.log("接受到消息:" + e.data);
                        var receiveMsg = document.getElementById("receiveMsg");
                        var html = receiveMsg.innerHTML;
                        receiveMsg.innerHTML = html + "<br/>" + e.data;
                    }
            } else {
                alert("浏览器不支持websocket协议...");
            }
        },
        chat: function () {
            var msg = document.getElementById("msgContent");
            CHAT.socket.send(msg.value);
        }
    };

    CHAT.init();

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

测试效果

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值