【WebSocket服务器】 1.服务器netty 2.客户端creator 3.fastjson通讯协议

1.客户端

    start() {
        // init logic
        this.label.string = this.text;

        let socket = new WebSocket("ws://localhost:6080/ws"); // H5标准,底层做好了;
        socket.binaryType = "arraybuffer";
        socket.onopen = function () {
            cc.log("connect succ!!!");

            let content = "";

            for (let i = 0; i < 1; i++) {
                content += "你好啊,朋友";
            }

            this.sendMessage(socket, OPCodeConfig.OP_CHAT_BROADCAST, {
                content: content,
            })

        }.bind(this);

        socket.onmessage = function (event) {
            let obj = JSON.parse(event.data);
            cc.log(obj);
        }.bind(this);
    }

    sendMessage(socket, msgCode, params) {
        let obj = {
            msgCode: msgCode,
            params: params,
        };

        let msg = JSON.stringify(obj);

        socket.send(msg);
    }

2.服务器

package gamebase;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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 vega.gameserver.GSIOHandler;
import vega.gameserver.GSServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WsManager {
    private static Logger logger = LoggerFactory.getLogger(GSServer.class);

    private static EventLoopGroup bossGroup;
    private static EventLoopGroup workerGroup;

    public static void start() {
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();

        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup);
        b.channel(NioServerSocketChannel.class);
        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(
                        new HttpServerCodec(),
                        new ChunkedWriteHandler(),
                        new HttpObjectAggregator(65536),
                        new WebSocketServerProtocolHandler("/ws"),
                        new GSIOHandler()
                );
            }
        });

        try {
            int port = 6080;
            ChannelFuture f = b.bind(port).sync();
            if (f.isSuccess()) {
                logger.info("ws server start, listen port:{}", port);
            }
//            f.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    public static void stop() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();

        logger.info("game server shutdown!!!");
    }
}

package vega.gameserver;

import com.alibaba.fastjson.JSONObject;
import gamebase.BusinessThreadManager;
import gamebase.processor.CmdExecutor;
import gamebase.processor.ProcessorManager;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

public class GSIOHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    private static Logger logger = LoggerFactory.getLogger(GSIOHandler.class);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {

        try {
            JSONObject jo = JSONObject.parseObject(textWebSocketFrame.text());
            // 命令号(找那个method)
            int msgCode = jo.getInteger("msgCode");
            // 消息体
            JSONObject params = jo.getJSONObject("params");

            CmdExecutor cmdExecutor = ProcessorManager.getCmdExecutor(msgCode);
            if (cmdExecutor == null) {
                throw new RuntimeException("请求参数找不到msgCode:" + msgCode);
            }
            Object handler = cmdExecutor.getHandler();
            Method method = cmdExecutor.getMethod();
            boolean isLoginInterface = cmdExecutor.isLoginInterface();


//            Object[] paramArr = new Object[]{role, params};
//            if (!cmdExecutor.isLoginInterface()) {
//                if (StringUtil.isNullOrEmpty(role.getRid())) {
//                    throw new RuntimeException("不是登陆接口必须含有rid:" + msgCode);
//                }
//            }
//
//            Object ret = method.invoke(handler, paramArr);
//            if (ret != null) {
//                return (JSONObject) ret;
//            }
//
//            return null;

            BusinessThreadManager.runTask(1, () -> {
                try {
                    JSONObject retMsg = ProcessorManager.processMessage(null, msgCode, params);
                    // 将处理结果发给客户端
                    if (retMsg != null) {
                        ctx.writeAndFlush(new TextWebSocketFrame(retMsg.toJSONString()));
                    }
                } catch (Exception e) {
                    logger.error("", e);
                }
            });

        } catch (Exception e) {
            logger.error("", e);
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("客户端异常:" + ctx.channel().remoteAddress());
        cause.printStackTrace();
        ctx.close();
    }

}

package gamebase.processor;

import com.alibaba.fastjson.JSONObject;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.StringUtil;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vega.gameserver.model.Role;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class ProcessorManager {
    private static Logger logger = LoggerFactory.getLogger(ProcessorManager.class);

    private static Map<Integer, CmdExecutor> interfaceMap = new HashMap<>();

    public static void init(String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set<Class<?>> httpHandlerSet = reflections.getTypesAnnotatedWith(Processor.class);
        try {
            for (Class<?> clazz : httpHandlerSet) {
                Object handler = clazz.newInstance();
                Processor processor = clazz.getAnnotation(Processor.class);
                Method[] methods = clazz.getDeclaredMethods();

                for (Method method : methods) {
                    Interface interfaceMethod = method.getAnnotation(Interface.class);
                    if (interfaceMethod != null) {
                        int msgCode = interfaceMethod.msgCode();

                        interfaceMap.put(msgCode, CmdExecutor.valueOf(method, method.getParameterTypes(), handler, interfaceMethod.loginInterface()));
                    }
                }
            }
        } catch (Exception e) {
            logger.error("", e);
        }
    }


    public static CmdExecutor getCmdExecutor(int msgCode) {
        return interfaceMap.get(msgCode);
    }

    public static JSONObject processMessage(Role role, int msgCode, JSONObject params) throws Exception {
        CmdExecutor cmdExecutor = interfaceMap.get(msgCode);
        if (cmdExecutor == null) {
            throw new RuntimeException("请求参数找不到msgCode:" + msgCode);
        }
        Object handler = cmdExecutor.getHandler();
        Object[] paramArr = new Object[]{role, params};
        Method method = cmdExecutor.getMethod();

        if (!cmdExecutor.isLoginInterface()) {
            if (StringUtil.isNullOrEmpty(role.getRid())) {
                throw new RuntimeException("不是登陆接口必须含有rid:" + msgCode);
            }
        }

        Object ret = method.invoke(handler, paramArr);
        if (ret != null) {
            return (JSONObject) ret;
        }

        return null;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值