当前位置:   article > 正文

使用netty实现一个多人聊天室--failed: Error during WebSocket handshake: Unexpected response code: 200

failed: error during websocket handshake: unexpected response code: 200

初次接触netty , 本文主要内容如下:

遇到的小bug

在使用netty进行websocket编程(实现一个简单的聊天室)时,我遇到了这样一个奇怪问题failed: Error during WebSocket handshake: Unexpected response code: 200
google了一下发现还真有人也有这个错误。最后发现这是一个很低级的错误:
因为我之前写了一个websocket服务器端口还没释放,于是又写了一个新的websocket服务器同时运行,就出现了这个错误。


解决方法:关掉idea中所有运行的websocket端口,重新运行程序。
我的服务器端代码如下:

ChannelFuture future= server.bind(8080).sync()
  • 1

js客户端代码:

//169.254.184.238是我用ipconfig Ping出来的本机ip地址
CHAT.socket =new WebSocket("ws://169.254.184.238:8080/ws");
  • 1
  • 2

然后一个简单的多人聊天室的小bug就解决了

聊天室后端代码:

package com.netty.websocket;

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;

/**
 * netty服务器端启动类
 * @author zgm
 * @date 2018/10/4 12:08
 */
public class WSServer {
    public static void main(String[] args) throws  Exception{
        EventLoopGroup mainGroup = new NioEventLoopGroup();
        EventLoopGroup subGroup= new NioEventLoopGroup();

        try {
            ServerBootstrap server=new ServerBootstrap();
            server.group(mainGroup,subGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new WSServerInitializer());

            ChannelFuture future= server.bind(8080).sync();

            future.channel().closeFuture().sync();
        } finally {
            mainGroup.shutdownGracefully();
            subGroup.shutdownGracefully();
        }

    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
package com.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.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * 通道初始化
 * @author zgm
 * @date 2018/10/4 12:12
 */
public class WSServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.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 服务器处理的协议,用于指定给客户端访问的路由: /ws
         * 本handler会帮你处理一些繁重复杂的事
         * 会帮你处理握手动作 : handshaking (close, ping, pong) ping+pong=心跳
         * 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应frames不同
         */
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

        //自定义的handler
        pipeline.addLast(new ChatHandler());
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
package com.netty.websocket;
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
 * TextWebSocketFrame: 在netty中,,是用于为websocket专门处理文本的对象,frame是消息的载体
 *
 * @author zgm
 * @date 2018/10/4 12:26
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //用于记录和管理所有客户端的channel
    private static ChannelGroup clients= new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //获取客户端传输过来的消息
        String content = textWebSocketFrame.text();
        System.out.println("接受到的数据: " + content);

/*        for(Channel channel : clients){
            channel.writeAndFlush(new TextWebSocketFrame("【服务器在 " + LocalDateTime.now())+"接收到消息】 , 消息为: " + content);
        }*/
        //下面这条语句和上面的for循环一样效果
        clients.writeAndFlush(new TextWebSocketFrame("【服务器在 " + LocalDateTime.now()+"接收到消息】 , 消息为: " + content));
    }

    /**
     * 当客户端连接服务器端之后(打开连接)
     * 获取客户端的channel,并放到ChannelGroup中去进行管理
     * @param ctx
     * @throws Exception
     */
    @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("客户端断开,channel对应的长id为: "+ ctx.channel().id().asLongText());
        System.out.println("客户端断开,channel对应的短id为: "+ctx.channel().id().asShortText());
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

聊天室前端代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>hello</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:orange;"></div>
		
		
		<script type="application/javascript">
			
			window.CHAT= {
				socket: null,
				init:function(){
					if (window.WebSocket){
						CHAT.socket =new WebSocket("ws://169.254.184.238:8080/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>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

以上代码就实现了一个简单的聊天室。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/179231
推荐阅读
相关标签
  

闽ICP备14008679号