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>

测试效果

目录
相关文章
|
6月前
|
缓存 网络协议 算法
Netty的基础入门(上)
Netty的基础入门(上)
223 1
|
6天前
|
消息中间件 编解码 网络协议
Netty从入门到精通:高性能网络编程的进阶之路
【11月更文挑战第17天】Netty是一个基于Java NIO(Non-blocking I/O)的高性能、异步事件驱动的网络应用框架。使用Netty,开发者可以快速、高效地开发可扩展的网络服务器和客户端程序。本文将带您从Netty的背景、业务场景、功能点、解决问题的关键、底层原理实现,到编写一个详细的Java示例,全面了解Netty,帮助您从入门到精通。
24 0
|
1月前
|
网络协议 前端开发 JavaScript
WebSocket 教程汇总指南,从入门到熟练
本文将带你从零开始,逐步掌握 WebSocket 的基本概念、实现方法和应用场景,通过一系列详细的教程和实践案例,帮助你从入门到熟练地使用 WebSocket 技术。无论你是初学者还是有一定经验的开发者,本文都能为你提供有价值的信息和指导。
|
5月前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
578 0
|
1月前
|
网络协议 安全 JavaScript
Web实时通信的学习之旅:WebSocket入门指南及示例演示
Web实时通信的学习之旅:WebSocket入门指南及示例演示
124 0
|
3月前
|
API 开发者
Netty运行原理问题之Netty实现低开发门槛的问题如何解决
Netty运行原理问题之Netty实现低开发门槛的问题如何解决
|
3月前
|
前端开发 网络协议 物联网
Django Web:搭建Websocket服务器(入门篇)
Django Web:搭建Websocket服务器(入门篇)
70 1
|
3月前
|
网络协议 前端开发 Go
[go笔记]websocket入门
[go笔记]websocket入门
|
4月前
|
存储 前端开发 Go
golang怎么搭建Websocket聊天室服务端
连接的添加和移除 添加连接: 当一个新的WebSocket连接建立时,服务器需要将这个连接添加到全局的连接列表中。多个连接可能同时建立,从而导致多个并发操作试图修改连接列表。 移除连接: 当一个WebSocket连接断开时,服务器需要将这个连接从全局的连接列表中移除。如果多个连接同时断开,可能会导致并发修改连接列表。
|
5月前
|
移动开发 安全 前端开发
技术心得记录:基于webSocket的聊天室
技术心得记录:基于webSocket的聊天室