netty结合websocket使用

netty结合websocket使用

首先需要在后台建立netty服务器启动类;

package com.cxy;

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

/***
 * @ClassName: WsNetty
 * @Description:
 * @Auther: cxy
 * @Date: 2019/2/5:14:15
 * @version : V1.0
 */
public class WsNetty {
    public static void main(String[] args) throws InterruptedException {
        /* 主从线程组模型
        */
        EventLoopGroup mainGroup =new NioEventLoopGroup();
        EventLoopGroup subGroup=new NioEventLoopGroup();
        try {
      //创建核心类 ServerBootstrap serverBootstrap
=new ServerBootstrap(); serverBootstrap.group(mainGroup,subGroup) .channel(NioServerSocketChannel.class) .childHandler(new WSServerInitialzer());//添加助手类 ChannelFuture channelFuture= serverBootstrap.bind(8088).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { mainGroup.shutdownGracefully(); subGroup.shutdownGracefully();//优雅的关闭主从线程池 } } }

第二创建初始化类;

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;

public class WSServerInitialzer extends ChannelInitializer {

    @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中的编程,都会使用到此hanler
        pipeline.addLast(new HttpObjectAggregator(1024*64));
        
        // ====================== 以上是用于支持http协议    ======================
        
        // ====================== 以下是支持httpWebsocket ======================
        
        /**
         * websocket 服务器处理的协议,用于指定给客户端连接访问的路由 : /ws
         * 本handler会帮你处理一些繁重的复杂的事
         * 会帮你处理握手动作: handshaking(close, ping, pong) ping + pong = 心跳
         * 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同
         */
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        
        // 自定义的handler
        pipeline.addLast(new ChatHandler());
    }

}

第三步:创建助手类

import java.time.LocalDateTime;

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;

/**
 * 
 * @Description: 处理消息的handler
 * TextWebSocketFrame: 在netty中,是用于为websocket专门处理文本的对象,frame是消息的载体
 */
public class ChatHandler extends SimpleChannelInboundHandler {

    // 用于记录和管理所有客户端的channle
    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);
        
//        for (Channel channel: clients) {
//            channel.writeAndFlush(
//                new TextWebSocketFrame(
//                        "[服务器在]" + LocalDateTime.now() 
//                        + "接受到消息, 消息为:" + content));
//        }
        // 下面这个方法,和上面的for循环,一致
        clients.writeAndFlush(
                new TextWebSocketFrame(
                        "[服务器在]" + LocalDateTime.now() 
                        + "接受到消息, 消息为:" + content));
        
    }

    /**
     * 当客户端连接服务端之后(打开连接)
     * 获取客户端的channle,并且放到ChannelGroup中去进行管理
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        clients.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        // 当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel
//        clients.remove(ctx.channel());
        System.out.println("客户端断开,channle对应的长id为:" 
                            + ctx.channel().id().asLongText());
        System.out.println("客户端断开,channle对应的短id为:" 
                            + ctx.channel().id().asShortText());
    }

    
    
}

前端页面:



    
        "utf-8" />
        
    
    
        
发送消息
"text" id="msgContent" /> "button" value="点我发送" οnclick="chat.chat1()" />
接受消息
"receiveMsg" style="background-color: gainsboro;">

测试结果:

netty结合websocket使用_第1张图片

 

posted @ 2019-02-05 16:37 动手的程序员 阅读( ...) 评论( ...) 编辑 收藏

你可能感兴趣的:(netty结合websocket使用)