Netty实现WebSocket通信案例

Netty实现WebSocket通信


基于springboot2.x版本实现






menu

maven依赖
自定义handler
自定义子处理器
Server
WebSocket启动配置类
前端测试页





maven依赖


<dependency>
  <groupId>io.nettygroupId>
  <artifactId>netty-allartifactId>
  <version>4.1.25.Finalversion>
dependency>





自定义handler

package com.credi.websocket;

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.time.LocalDateTime;

/**
 * 自定义的handler , 本handler用于处理消息
 * TextWebSocketFrame:
 * @Author: He Xingchi
 * Created by ALIENWARE on 2019/12/21.
 */
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 content = msg.text();
        System.out.println("接收到来自客户端的数据: " + content );

//        遍历用以记录和管理所有客户端的channel中的通道channel
        for (Channel channel : clients){
    //将该客户端channel通道收到的消息刷出给每一个channel通道
            /**
             * writeAndFlush : 将消息刷出给该channel , 虽然接受的参数类型为Object , 但是参数不能是String , 而是TextWebSocketFrame
             */
            channel.writeAndFlush(new TextWebSocketFrame(LocalDateTime.now() + " [服务器接收到消息:] " + " 接收到消息, 消息为: " + content));
        }
//        用以记录和管理所有客户端的channel其实自带一个writeAndFlush函数 : 作用是向维护的所有通道刷出消息 , 作用是一样的
        //clients.writeAndFlush(new TextWebSocketFrame(LocalDateTime.now() + " [服务器接收到消息:] " + " 接收到消息, 消息为: " + content));
    }

    /**
     *  当客户端链接服务端之后(打开链接)
     *  获取客户端的channel , 并且放到ChannelGroup中进行管理
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
   
//        处理客户端所对应的的channal的通道
        Channel channel = ctx.channel();//当客户端和服务端链接之后 , 就有了一个双向的通道channel
        clients.add(channel); // 将通道channel交给用以记录和管理所有客户端的channel进行维护和管理
    }

//    用户离开或关闭客户端触发的方法
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
   
        //clients.remove(ctx.channel()); //当客户端关闭 , 移除链接客户端和服务端的双向通道的chuannal
//        但以上这句话是多余的 , 因为客户端关闭之后 , 用以记录和管理所有客户端的channel会自动把通道移除
        System.out.println(ctx.channel().id()); //打印通道的id(每一个通道channel都有一份唯一的id , 长id(asLongText)和短id(asShortText))
        System.out.println("客户端断开 , channle对应的长id为: " + ctx.channel().id().asLongText());
        System.out.println("客户端断开 , channle对应的短id为: " + ctx.channel().id().asShortText()); // 短id可能出现重复
    }

}







自定义子处理器

package com.credi.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.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.springframework.context.annotation.Configuration;

/**
 * 自定义子处理器
 * @Author: He Xingchi
 * Created by ALIENWARE on 2019/12/21.
 */
@Configuration
//@EnableWebSocket
public class WSServerInitialzer extends ChannelInitializer<SocketChannel> {
   
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
   
        ChannelPipeline pipeline = ch.pipeline();

//        websocket 基于http协议 , 所以要有http编解码器
        pipeline.addLast(new HttpServerCodec());
//        对写大数据流的支持
        pipeline.addLast(new ChunkedWriteHandler());
//        聚合器 , 对httpMessage进行聚合 , 聚合成FullHttpRequest或FullHttpResponse
//        几乎在netty中的编程 , 都会使用此handler
        pipeline.addLast(new HttpObjectAggregator(1024*64));

//        =============================  以上是用于支持http协议  ==========================================>>>>>>>>>>

        /**
         *  websocket 服务器处理的协议 , 用于指定连接客服端访问的路由 ip:端口/ws
         *  本handler会帮你处理一些繁重的复杂的事
         *  会帮你处理websocket的握手动作: handshaking(close, ping , pong)  ping + pong = 心跳
         *  对于websocket来讲 , 都是以frames进行传输的 , 不同的数据类型对应的frames也不同
         */
        pipeline.addLast(new 

你可能感兴趣的:(java,java,websocket,netty,网络)