使用netty搭建一个简单的聊天室
生活随笔
收集整理的這篇文章主要介紹了
使用netty搭建一个简单的聊天室
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.導入maven依賴
? ? ? ?<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.25.Final</version></dependency>2.ChannelHandler
我們需要寫一個處理消息的handler,繼承SimpleChannelInboundHandler即可,然后實現我們需要實現的幾個方法。
因為我們要搭建的是一個聊天室,所以需要有一個對象ChannelGroup來將所有客戶端保存起來。每當一個用戶連接到服務器,就將該用戶所在的通道加入到該對象中。當任一用戶發送消息,將消息遍歷發送給所有用戶。
/*** 處理消息的handler* TextWebSocketFrame: 在netty中,是用于為websocket專門處理文本的對象,frame是消息的載體*/ public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { ?/*** 用來保存所有的客戶端連接*/private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm"); ?/*** 當Channel中有新的事件消息會自動調用*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {// 當接收到數據后會自動調用 ?// 獲取客戶端發送過來的文本消息String text = msg.text();System.out.println("接收到消息數據為:" + text); ?for (Channel client : clients) {// 將消息發送到所有的客戶端client.writeAndFlush(new TextWebSocketFrame(sdf.format(new Date()) + ":" + text));}} ?/*** 當有新的客戶端連接服務器之后,會自動調用這個方法*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {// 將新的通道加入到clientsclients.add(ctx.channel());} }3.ChannelHandler
ChannelInitializer的主要目的是為程序員提供了一個簡單的工具,用于在某個Channel注冊到EventLoop后,對這個Channel執行一些初始化操作。ChannelInitializer雖然會在一開始被注冊到Channel相關的pipeline里,但是在初始化完成之后,ChannelInitializer會將自己從pipeline中移除,不會影響后續的操作。
/*** 通道初始化器* 用來加載通道處理器(ChannelHandler)*/ public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> { ?// 初始化通道// 在這個方法中去加載對應的ChannelHandler@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 獲取管道,將一個一個的ChannelHandler添加到管道中ChannelPipeline pipeline = ch.pipeline(); ?// 添加一個http的編解碼器pipeline.addLast(new HttpServerCodec());// 添加一個用于支持大數據流的支持pipeline.addLast(new ChunkedWriteHandler());// 添加一個聚合器,這個聚合器主要是將HttpMessage聚合成FullHttpRequest/Responsepipeline.addLast(new HttpObjectAggregator(1024 * 64)); ?// 需要指定接收請求的路由// 必須使用以ws后綴結尾的url才能訪問pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); ?// 添加自定義的Handlerpipeline.addLast(new ChatHandler());} }4.客戶端server
public class WebSocketNettyServer {public static void main(String[] args) {// 創建兩個線程池NioEventLoopGroup mainGrp = new NioEventLoopGroup(); // 主線程池NioEventLoopGroup subGrp = new NioEventLoopGroup(); // 從線程池 ?try {// 創建Netty服務器啟動對象ServerBootstrap serverBootstrap = new ServerBootstrap(); ?// 初始化服務器啟動對象serverBootstrap// 指定使用上面創建的兩個線程池.group(mainGrp, subGrp)// 指定Netty通道類型.channel(NioServerSocketChannel.class)// 指定通道初始化器用來加載當Channel收到事件消息后,// 如何進行業務處理.childHandler(new WebSocketChannelInitializer()); ?// 綁定服務器端口,以同步的方式啟動服務器ChannelFuture future = serverBootstrap.bind(9090).sync();// 等待服務器關閉future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {// 優雅關閉服務器mainGrp.shutdownGracefully();subGrp.shutdownGracefully();} ?} }5.html頁面
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>在線聊天室</title> </head> <body><input type="text" id="message"><input type="button" value="發送消息" onclick="sendMsg()"> ?接收到的消息:<p id="server_message" style="background-color: #AAAAAA"></p> ?<script> ?var websocket = null; ?// 判斷當前瀏覽器是否支持websocketif(window.WebSocket) {websocket = new WebSocket("ws://127.0.0.1:9090/ws"); ?websocket.onopen = function() {console.log("建立連接.");}websocket.onclose = function() {console.log("斷開連接");}websocket.onmessage = function(e) {console.log("接收到服務器消息:" + e.data);var server_message = document.getElementById("server_message");server_message.innerHTML += e.data + "<br/>";}}else {alert("當前瀏覽器不支持web socket");} ?function sendMsg() {var message = document.getElementById("message");websocket.send(message.value);}</script> </body> </html>6.測試
打開多個頁面,然后發送消息,不同頁面都能實時的顯示不同頁面發送的消息。
?
?
?
總結
以上是生活随笔為你收集整理的使用netty搭建一个简单的聊天室的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MYSQL数据库设计原则
- 下一篇: 使用netty实现一个类似于微信的聊天功