赞
踩
在使用netty进行websocket编程(实现一个简单的聊天室)时,我遇到了这样一个奇怪问题failed: Error during WebSocket handshake: Unexpected response code: 200。
google了一下发现还真有人也有这个错误。最后发现这是一个很低级的错误:
因为我之前写了一个websocket服务器端口还没释放,于是又写了一个新的websocket服务器同时运行,就出现了这个错误。
解决方法:关掉idea中所有运行的websocket端口,重新运行程序。
我的服务器端代码如下:
ChannelFuture future= server.bind(8080).sync()
js客户端代码:
//169.254.184.238是我用ipconfig Ping出来的本机ip地址
CHAT.socket =new WebSocket("ws://169.254.184.238:8080/ws");
然后一个简单的多人聊天室的小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(); } } }
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()); } }
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()); } }
<!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>
以上代码就实现了一个简单的聊天室。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。