missing upgrade : Serve both http and ws on netty

2019-08-11 09:35发布

问题:

I'm writing a chat application on netty.

I tried to serve both HTTP and WS, but http responses is only these message

not a WebSocket handshake request: missing upgrade

Here is my code snippets.

in InitChannel method

p.addLast(new HttpServerCodec())
.addLast(new HttpObjectAggregator(65536))
.addLast( new LoggingHandler(LogLevel.INFO))
.addLast(new WebSocketServerProtocolHandler("/chat"),
        new WsUserAcceptHandler(), new WsChatServerHandler())
.addLast(new HttpStaticFileHandler("/", ChatServer.index))
.addLast(new HttpNotFoundHandler());

and on channelRead, both WsUserAcceptHandler, WsChatHandler handles only TextWebSocketFrame, and the others are ctx.fireChannelRead(msg)

WsUserAcceptHandler

@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        System.out.println("WsUserAcceptHandler#channelRead :" + msg.getClass());
        if (msg instanceof TextWebSocketFrame) {
            TextWebSocketFrame tMsg = (TextWebSocketFrame) msg;
            ChatMessage chatMsg = ChatMessage.parse(tMsg.text());

            if (chatMsg.getCommand().equals("CONN")) {


                SqlSession sqlSession = SqlSessionFactoryManager
                        .getSqlSession();
                User u = new User();
                ChatRoom roomInfo = new ChatRoom();

                try {
                    u.setUserSessionkey(chatMsg.getSessionKey());
                    UserMapper userMapper = sqlSession
                            .getMapper(UserMapper.class);
                    u = userMapper.get(u);

                    ChatInfoMapper chatInfoMapper = sqlSession
                            .getMapper(ChatInfoMapper.class);
                    roomInfo = chatInfoMapper.getRoomInfo(chatMsg.getRoomNo());

                } catch (Exception e) {

                } finally {
                    sqlSession.close();
                }

                if (u != null) {
                    System.out.println("userInfo");
                    System.out.println(u.toString());

                    AttrKeys attrs = AttrKeys.getInstance();

                    ctx.channel().attr(attrs.sessionKey())
                            .set(u.getUserSessionkey());
                    ctx.channel().attr(attrs.userInfo()).set(u);
                    currClients.registerUserChannelGroup(
                            String.valueOf(chatMsg.getRoomNo()), ctx.channel());

                    ChatDataMapper cdm = new ChatDataMapper();
                    List<ChatMessage> latests = cdm.gets(chatMsg.getRoomNo(), 20);

                    HashMap<String, Object> map = new HashMap<String, Object>();
                    map.put("recentMessages", latests);
                    map.put("roomInfo", roomInfo);

                    JsonResultSet<HashMap<String, Object>> res = new JsonResultSet<HashMap<String, Object>>();
                    res.setResultCode("S0000");
                    res.setResultMessage("Success");
                    res.setCommand(chatMsg.getCommand());
                    res.setResult(map);
                    System.out.println(res.toJsonString());

                    TextWebSocketFrame outputMsg = new TextWebSocketFrame(
                            res.toJsonString());
                    ctx.writeAndFlush(outputMsg);
                } else {
                    ctx.flush();
                }

                // ctx.writeAndFlush(outputMsg);
            } else if (chatMsg.getCommand().equals("DISCONN")) {
                ctx.channel().attr(sessionKeyAttr).get();
                currClients.unregisterUserChannelGroup(
                        String.valueOf(chatMsg.getRoomNo()), ctx.channel());

                ctx.fireChannelInactive();
            }
        }

        ctx.fireChannelRead(msg); // if not instance of TextWebsocketFrame
    }

WsChatServerHandler

@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        System.out.println("WsChatServerHandler##channelRead :" + msg.getClass());
        if(msg instanceof TextWebSocketFrame){
            ChatMessage chatMsg = ChatMessage.parse(((TextWebSocketFrame) msg).text());
//          chatMsg.setC_user_nm(ctx.channel().attr(sessionKeyAttr).get()  );
            if(chatMsg.getCommand().equals("TEXT")){
                ChannelGroup roomUsers = currClients.getUserChannelGroup(String.valueOf(chatMsg.getRoomNo ()));

                AttrKeys attrs = AttrKeys.getInstance();
                User u = ctx.channel().attr(attrs.userInfo()).get();


                JsonResultSet<ChatMessage> res = new JsonResultSet<ChatMessage>();
                res.setResultCode("S0000");
                res.setResultMessage("Success");
                res.setCommand(chatMsg.getCommand());

                chatMsg.setSessionKey(null);
                chatMsg.setCommand(null);

                chatMsg.setSeq(ChatServer.nextChatDataSeq());
                chatMsg.setUserSeq(u.getUserSeq());
                chatMsg.setUserNm(u.getUserNm());
                chatMsg.setUserType(u.getUserType());
                chatMsg.setUserThumb(StaticVar.default_img_url+u.getUserThumb()+"&imgMode=origin");
                chatMsg.setUserPic(StaticVar.default_img_url+u.getUserPic()+"&imgMode=thumb");

                ChatDataMapper mapper = new ChatDataMapper();
                mapper.put(chatMsg);

                System.out.println(chatMsg.toString());

                res.setResult(chatMsg);

                TextWebSocketFrame outputMsg = new TextWebSocketFrame(res.toJsonString());

                sendPush(chatMsg, String.valueOf(chatMsg.getRoomNo()));
//              gcmTest(chatMsg);

                roomUsers.writeAndFlush(outputMsg);
            } else if(chatMsg.getCommand().equals("MORE")){

            }
        } else {
            ctx.fireChannelRead(msg);
        }
    }

回答1:

I solved. It was Netty version problem.

I used before Netty 4.1.0.CR6 then I tried changing both after version and 4.0.0 then my problem is gone.