Netty入门到超神系列-基于WebSocket开发聊天室

简介: 在很多的网站中都嵌入有聊天功能,最理想的方式就是使用WebSocket来开发,屏幕面前的你如果不清楚WebSocket的作用可以自己去百度一下,Netty提供了WebSocket支持,这篇文章将使用Netty作为服务器,使用WebSocket开发一个简易的聊天室系统。

在很多的网站中都嵌入有聊天功能,最理想的方式就是使用WebSocket来开发,屏幕面前的你如果不清楚WebSocket的作用可以自己去百度一下,Netty提供了WebSocket支持,这篇文章将使用Netty作为服务器,使用WebSocket开发一个简易的聊天室系统。

服务端

导入依赖

<dependencies><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.42.Final</version></dependency></dependencies>

Netty提供了 WebSocketServerProtocolHandler ,它能够把平台的Http协议升级为WebSocket的WS协议,服务端代码如下

publicclassNettySocketServer {
publicstaticvoidmain(String[] args) {
NioEventLoopGroupbossGroup=newNioEventLoopGroup();
NioEventLoopGroupworkGroup=newNioEventLoopGroup();
ServerBootstrapbootstrap=newServerBootstrap();
try {
bootstrap.group(bossGroup, workGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(newChannelInitializer<SocketChannel>() {
protectedvoidinitChannel(SocketChannelchannel) throwsException {
ChannelPipelinepipeline=channel.pipeline();
//设置http编码器pipeline.addLast(newHttpServerCodec());
//支持以块的方式写数据,添加块处理器pipeline.addLast(newChunkedWriteHandler());
//http请求是分段的,通过该处理器聚合分段pipeline.addLast(newHttpObjectAggregator(8192));
//支持websocket长连接,添加SocketServer处理器,把http升级为ws协议//客户端请求方式为:ws://localhost:8000/hellopipeline.addLast(newWebSocketServerProtocolHandler("/hello"));
//处理请求,执行业务的Hnadlerpipeline.addLast(newMyWebSorcketServerHandler());
                }
            });
//启动服务器ChannelFuturesync=bootstrap.bind(8000).sync();
sync.channel().closeFuture().sync();
        }catch (Exceptione){
e.printStackTrace();
        }finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
        }
    }
}
  • 因为使用http,所以需要通过pipeline添加http编码器 HttpServerCodec
  • WebSocketServerProtocolHandler : WebSocket支持,把http升级为ws协议
  • MyWebSorcketServerHandler :该处理器是服务器处理请求的处理器

编写请求处理器

//消息进站处理 ,TextWebSocketFrame:WebSokcet消息是以“帧 Frame”的方式参数,该类是针对Text的数据publicclassMyWebSorcketServerHandlerextendsSimpleChannelInboundHandler<TextWebSocketFrame> {
//保存所有客户端privatestaticChannelGroupchannels=newDefaultChannelGroup(GlobalEventExecutor.INSTANCE);
privateSimpleDateFormatdateFormat=newSimpleDateFormat("mm:ss");
//读取消息protectedvoidchannelRead0(ChannelHandlerContextctx, TextWebSocketFramemsg) throwsException {
Stringmessage=dateFormat.format(newDate())+":%s:"+msg.text();
System.out.println("收到消息: "+ctx.channel().remoteAddress()+":"+message);
StringsendMsg=String.format(message, ctx.channel().remoteAddress());
//把消息广播给所有的客户端channels.writeAndFlush(newTextWebSocketFrame(sendMsg));
    }
@OverridepublicvoidhandlerAdded(ChannelHandlerContextctx) throwsException {
Stringmessage=dateFormat.format(newDate())+":"+ctx.channel().remoteAddress()+" 加入聊天室";
//添加客户端的集合channels.add(ctx.channel());
//自动把消息广播给其客户端channels.writeAndFlush(newTextWebSocketFrame(message));
System.out.println("服务器收到链接 ID="+ctx.channel().id().asLongText());
    }
@OverridepublicvoidhandlerRemoved(ChannelHandlerContextctx) throwsException {
Stringmessage=dateFormat.format(newDate())+":"+ctx.channel().remoteAddress()+" 断开连接";
channels.writeAndFlush(newTextWebSocketFrame(message));
    }
//客户端退出@OverridepublicvoidchannelInactive(ChannelHandlerContextctx) throwsException {
Stringmessage=dateFormat.format(newDate())+":"+ctx.channel().remoteAddress()+" 退出聊天室";
channels.writeAndFlush(newTextWebSocketFrame(message));
System.out.println(message);
    }
@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx, Throwablecause) throwsException {
System.out.println("发生异常 ID="+ctx.channel().id().asLongText()+";msg="+cause.getMessage());
ctx.channel().close();
    }
}
  • DefaultChannelGroup : 该group用来存储所有的客户端的channel
  • channelRead0 : 当接收到请求拿到数据的方法,需要把数据广播给所有客户端

客户端编写

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>WebSocket测试</title></head><body><textareaid="viewBody"rows="10"style="width: 500px"></textarea><br/><inputid="sendInput"type="text"style="width: 450px"><buttonid="sendBtn"onclick="send()">发送</button></body><script>varsocket;
if(!window.WebSocket){
alert("浏览器不支持");
    }else{
//创建客户端socket=newwindow.WebSocket("ws://localhost:8000/hello");
//当收到消息socket.onmessage=function (event) {
varinput=document.getElementById("viewBody");
input.value=input.value+"\n"+event.data;
        }
//打开链接socket.onopen=function (event) {
varinput=document.getElementById("viewBody");
input.value="成功加入聊天室"+"\n";
        }
//关闭链接socket.onclose=function (event) {
varinput=document.getElementById("viewBody");
input.value=input.value+"\n"+"退出聊天室";
        }
functionsend(){
if(socket&&socket.readyState==WebSocket.OPEN){
letsendInput=document.getElementById("sendInput");
letvalue=sendInput.value;
socket.send(value);
sendInput.value="";
            }
        }
    }
</script></html>

测试效果

目录
相关文章
|
2月前
|
网络协议 JavaScript 前端开发
netty 实现 websocket
netty 实现 websocket
78 1
|
2月前
|
缓存 网络协议 算法
Netty的基础入门(上)
Netty的基础入门(上)
128 0
|
2月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
171 0
|
2月前
|
Java Unix Linux
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
当涉及到网络通信和高性能的Java应用程序时,Netty是一个强大的框架。它提供了许多功能和组件,其中之一是JNI传输。JNI传输是Netty的一个特性,它为特定平台提供了高效的网络传输。 在本文中,我们将深入探讨Netty提供的特定平台的JNI传输功能,分析其优势和适用场景。我们将介绍每个特定平台的JNI传输,并讨论其性能、可靠性和可扩展性。通过了解这些特定平台的JNI传输,您将能够更好地选择和配置适合您应用程序需求的网络传输方式,以实现最佳的性能和可靠性。
96 7
【Netty技术专题】「原理分析系列」Netty强大特性之Native transports扩展开发实战
|
1月前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
214 0
|
22天前
|
移动开发 安全 前端开发
技术心得记录:基于webSocket的聊天室
技术心得记录:基于webSocket的聊天室
|
2月前
|
存储 JavaScript Java
基于 WebSocket 打造聊天室
基于 WebSocket 打造聊天室
|
2月前
|
小程序 Java 编译器
性能工具之JMeter 微信小程序 WebSocket 脚本入门
【5月更文挑战第12天】性能工具之JMeter 微信小程序 WebSocket 脚本入门
61 1
|
2月前
|
前端开发 JavaScript Java
Springboot+Netty+WebSocket搭建简单的消息通知
这样,你就建立了一个简单的消息通知系统,使用Spring Boot、Netty和WebSocket实现实时消息传递。你可以根据具体需求扩展和改进该系统。
88 1
|
2月前
|
前端开发 JavaScript Java
【十五】springboot整合WebSocket实现聊天室
【十五】springboot整合WebSocket实现聊天室
69 0