Netty实现聊天通信(4.0)
来源:互联网 发布:苏州微信营销闻道网络 编辑:程序博客网 时间:2024/06/07 22:58
以下是netty4.0的代码,如果是5.0的代码请参考 —>
Netty之——基于Netty5.0高级案例NettyWebsocket
http://blog.csdn.net/l1028386804/article/details/55026558
1、Java代码
package com.test.netty4; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.FullHttpRequest; public interface IHttpService { void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest request); }
package com.test.netty4; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.websocketx.WebSocketFrame; public interface IWebSocketService { void handleFrame(ChannelHandlerContext ctx, WebSocketFrame frame); }
package com.test.netty4; import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.Channel;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelId;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.EventLoopGroup;import io.netty.channel.group.ChannelGroup;import io.netty.channel.group.DefaultChannelGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.http.FullHttpRequest;import io.netty.handler.codec.http.HttpHeaderNames;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpMethod;import io.netty.handler.codec.http.HttpObjectAggregator;import io.netty.handler.codec.http.HttpServerCodec;import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;import io.netty.handler.codec.http.websocketx.WebSocketFrame;import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;import io.netty.handler.stream.ChunkedWriteHandler;import io.netty.util.AttributeKey;import io.netty.util.concurrent.GlobalEventExecutor; public class WebSocketServer implements IWebSocketService, IHttpService { public static void main(String[] args) { new WebSocketServer(9999).start(); } // ----------------------------static fields ----------------------------- private static final String HN_HTTP_CODEC = "HN_HTTP_CODEC"; private static final String HN_HTTP_AGGREGATOR = "HN_HTTP_AGGREGATOR"; private static final String HN_HTTP_CHUNK = "HN_HTTP_CHUNK"; private static final String HN_SERVER = "HN_LOGIC"; // handshaker attachment key private static final AttributeKey<WebSocketServerHandshaker> ATTR_HANDSHAKER = AttributeKey.newInstance("ATTR_KEY_CHANNELID"); private static final int MAX_CONTENT_LENGTH = 65536; private static final String WEBSOCKET_UPGRADE = "websocket"; private static final String WEBSOCKET_CONNECTION = "Upgrade"; private static final String WEBSOCKET_URI_ROOT_PATTERN = "ws://%s:%d"; // ------------------------ member fields ----------------------- private String host; // 绑定的地址 private int port; // 绑定的端口 /** * 保存所有WebSocket连接 */ private Map<ChannelId, Channel> channelMap = new ConcurrentHashMap<ChannelId, Channel>(); private ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); private final String WEBSOCKET_URI_ROOT; public WebSocketServer(int port) { this("localhost", port); } public WebSocketServer(String host, int port) { this.host = host; this.port = port; WEBSOCKET_URI_ROOT = String.format(WEBSOCKET_URI_ROOT_PATTERN, host, port); } public void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup); b.channel(NioServerSocketChannel.class); b.childHandler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { ChannelPipeline pl = ch.pipeline(); // 保存该Channel的引用 channelGroup.add(ch); channelMap.put(ch.id(), ch); System.out.println("new channel {}"+ ch); ch.closeFuture().addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { System.out.println("channel close {}"+ future.channel()); // Channel 关闭后不再引用该Channel channelMap.remove(future.channel().id()); } }); pl.addLast(HN_HTTP_CODEC, new HttpServerCodec()); pl.addLast(HN_HTTP_AGGREGATOR, new HttpObjectAggregator(MAX_CONTENT_LENGTH)); pl.addLast(HN_HTTP_CHUNK, new ChunkedWriteHandler()); pl.addLast(HN_SERVER, new WebSocketServerHandler(WebSocketServer.this, WebSocketServer.this)); } }); try { // 绑定端口 ChannelFuture future = b.bind(host, port).addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { System.out.println("websocket started."); } } }).sync(); future.channel().closeFuture().addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { System.out.println("server channel {} closed."+future.channel()); } }).sync(); } catch (InterruptedException e) { e.printStackTrace(); // logger.error(e.toString()); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } System.out.println("websocket server shutdown"); } /* * @see cc.lixiaohui.demo.netty4.websocket.IHttpService#handleHttpRequest(io.netty.handler.codec.http.FullHttpRequest) */ public void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { if (isWebSocketUpgrade(req)) { // 该请求是不是websocket upgrade请求 System.out.println("upgrade to websocket protocol"); String subProtocols = req.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL); WebSocketServerHandshakerFactory factory = new WebSocketServerHandshakerFactory(WEBSOCKET_URI_ROOT, subProtocols, false); WebSocketServerHandshaker handshaker = factory.newHandshaker(req); if (handshaker == null) {// 请求头不合法, 导致handshaker没创建成功 WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); } else { // 响应该请求 handshaker.handshake(ctx.channel(), req); // 把handshaker 绑定给Channel, 以便后面关闭连接用 ctx.channel().attr(ATTR_HANDSHAKER).set(handshaker);// attach handshaker to this channel } return; } // TODO 忽略普通http请求 System.out.println("ignoring normal http request"); } /* * @see * cc.lixiaohui.demo.netty4.websocket.IWebSocketService#handleFrame(io.netty * .channel.Channel, io.netty.handler.codec.http.websocketx.WebSocketFrame) */ public void handleFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { // text frame if (frame instanceof TextWebSocketFrame) { String text = ((TextWebSocketFrame) frame).text(); // TextWebSocketFrame rspFrame = new TextWebSocketFrame(text); System.out.println("recieve TextWebSocketFrame from channel {}"+ ctx.channel()); // 发给其他所有channel // for (Channel ch : channelMap.values()) { // if (ctx.channel().equals(ch)) { // continue; // } // TextWebSocketFrame rspFrame = new TextWebSocketFrame(text); // ch.writeAndFlush(rspFrame); // System.out.println("write text[{}] to channel {}"+ text+ ch); // } TextWebSocketFrame rspFrame = new TextWebSocketFrame(text); channelGroup.writeAndFlush(rspFrame); return; } // ping frame, 回复pong frame即可 if (frame instanceof PingWebSocketFrame) { System.out.println("recieve PingWebSocketFrame from channel {}"+ ctx.channel()); ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain())); return; } if (frame instanceof PongWebSocketFrame) { System.out.println("recieve PongWebSocketFrame from channel {}"+ ctx.channel()); return; } // close frame, if (frame instanceof CloseWebSocketFrame) { System.out.println("recieve CloseWebSocketFrame from channel {}"+ ctx.channel()); WebSocketServerHandshaker handshaker = ctx.channel().attr(ATTR_HANDSHAKER).get(); if (handshaker == null) { System.out.println("channel {} have no HandShaker"+ ctx.channel()); return; } handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain()); return; } // 剩下的是binary frame, 忽略 System.out.println("unhandle binary frame from channel {}"+ctx.channel()); } //三者与:1.GET? 2.Upgrade头 包含websocket字符串? 3.Connection头 包含 Upgrade字符串? private boolean isWebSocketUpgrade(FullHttpRequest req) { HttpHeaders headers = req.headers(); return req.getMethod().equals(HttpMethod.GET) && headers.get(HttpHeaderNames.UPGRADE).contains(WEBSOCKET_UPGRADE) && headers.get(HttpHeaderNames.CONNECTION).contains(WEBSOCKET_CONNECTION); } }
package com.test.netty4; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.websocketx.WebSocketFrame; public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object> { @SuppressWarnings("unused") private IWebSocketService websocketService; private IHttpService httpService; public WebSocketServerHandler(IWebSocketService websocketService, IHttpService httpService) { super(); this.websocketService = websocketService; this.httpService = httpService; } /* * @see * io.netty.channel.SimpleChannelInboundHandler#channelRead0(io.netty.channel * .ChannelHandlerContext, java.lang.Object) */ @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof FullHttpRequest) { httpService.handleHttpRequest(ctx, (FullHttpRequest) msg); } else if (msg instanceof WebSocketFrame) { websocketService.handleFrame(ctx, (WebSocketFrame) msg); } } /* * @see io.netty.channel.ChannelInboundHandlerAdapter#channelReadComplete(io.netty.channel.ChannelHandlerContext) */ @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { }}
2、html页面代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> </head> <script type="text/javascript"> var socket; if(!window.WebSocket){ window.WebSocket = window.MozWebSocket; } if(window.WebSocket){ socket = new WebSocket("ws://localhost:9999"); socket.onmessage = function(event){ appendln("接收:" + event.data); }; socket.onopen = function(event){ appendln("WebSocket 连接已建立"); }; socket.onclose = function(event){ appendln("WebSocket 连接已关闭"); }; }else{ alert("浏览器不支持WebSocket协议"); } function send(message){ if(!window.WebSocket){return;} if(socket.readyState == WebSocket.OPEN){ socket.send(message); appendln("发送:" + message); }else{ alert("WebSocket连接建立失败"); } } function appendln(text) { var ta = document.getElementById('responseText'); ta.value += text + "\r\n"; } function clear() { var ta = document.getElementById('responseText'); ta.value = ""; } </script> <body> <form onSubmit="return false;"> <input type = "text" name="message" value="你好啊"/> <br/><br/> <input type="button" value="发送 WebSocket 请求消息" onClick="send(this.form.message.value)"/> <hr/> <h3>服务端返回的应答消息</h3> <textarea id="responseText" style="width: 800px;height: 300px;"></textarea> </form> </body> </html>
3、启动 WebSocketServer 的main方法,然后打开多个html页面,即可实现聊天互通。更
此处是基于netty-all-4.1.12.Final.jar实现的。更详细的介绍可自行网络搜索。
阅读全文
1 0
- Netty实现聊天通信(4.0)
- Netty 实现聊天功能
- Netty 实现聊天功能
- Netty 实现聊天功能
- Netty 实现聊天功能
- Netty 实现聊天功能
- Netty 实现聊天功能
- Netty实现在线聊天
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty 实现 WebSocket 聊天功能
- Netty实现网络通信
- JAVA 多线程实现聊天(UDP通信 )
- java日期选择
- Packet for query is too large (12238 > 1024). You can change this value
- Android CardView 5.0以下间距问题
- 关于实习:不是总结的总结
- Android自动化压力测试图解教程——Monkey工具
- Netty实现聊天通信(4.0)
- 802.11无线网络学习(一):无线网络导论
- 谷歌搜索网站备份
- cocos code IDE 快捷键
- 设计模式——修正建造者模式
- WiFi探针的工作原理及采集的数据?
- 对于linux系统ifconfig中网卡名和网卡配置文件名称不同的解决办法
- Ubuntu安装scrapy
- Drawable初步介绍