Netty是由JBOSS提供的一个java开源框架,基于nio。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
官网:http://netty.io/
websocket通信示例如下(以下使用的netty版本为3.6.1):
说明:
通信服务端运用Netty,Netty中自带Jboss,iphone使用SocketRocket,进行推送数据。
随便画的草图:
SocketRocket关健代码(引入SocketRocket相关包和文件,官网上有下):
- (void)viewDidLoad { [super viewDidLoad]; //Socket _webSocket.delegate = nil; [_webSocket close]; _webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://127.0.0.0:8080/websocket"]]]; _webSocket.delegate = self; [_webSocket open]; NSLog(@"open success!"); } #pragma mark - SRWebSocketDelegate - (void)webSocketDidOpen:(SRWebSocket *)webSocket; { NSLog(@"Websocket Connected"); self.title = @"Connected!"; } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; { NSLog(@":( Websocket Failed With Error %@", error); _webSocket = nil; } - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message; { NSLog(@"Received \"%@\"", message); self.showTxt.text = message; } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; { NSLog(@"WebSocket closed"); self.title = @"Connection Closed! (see logs)"; _webSocket = nil; }
网页WebSocket关代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"/> <!-- WebSocket --> <!-- 注:有的浏览器需要判断进行特别处理websocket --> <script type="text/javascript"> var websocket; function init(){ window.WebSocket = window.WebSocket || window.MozWebSocket; if(!window.WebSocket){ alert("WebSocket not support browser!"); return; } websocket = new WebSocket("ws://127.0.0.0:8080/websocket"); websocket.onopen = function (evt){ onOpen(evt) }; websocket.onclose = function (evt){ onClose(evt) }; websocket.onmessage = function (evt){ onMessage(evt) }; websocket.onerror = function (evt){ onError(evt) }; } function onOpen(evt){ //alert("connect open!"); } function onClose(evt){ //alert("connect close!"); } function onMessage(evt){ /* var data = evt.data; if(!data){ return; } alert(data); */ var msg = document.getElementById('responseText'); msg.value = msg.value+"\n"+evt.data; } function onError(evt){ alert("connect error!"); } //发送消息 function send(message){ if(!window.WebSocket){ return; } if(websocket.readyState == WebSocket.OPEN){ websocket.send(message); }else{ alert("The websocket is not open!"); } } </script> </head> <body onload="init()"> <form onsubmit="return false;"> <input type="text" name="message"></input><br/> <input type="button" value="发送" onclick="send(this.form.message.value)"></input><br/> <h3>输出:</h3> <textarea id="responseText" style="width:500px;height:300px;"></textarea> </form> </body> </html>
Netty代码:
public class WebSocketServer { private final int port; public WebSocketServer(int port) { this.port = port; } public void run() { // Configure the server. ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // Set up the event pipeline factory. bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory()); // Bind and start to accept incoming connections. bootstrap.bind(new InetSocketAddress(port)); System.out.println("Web socket server started at port " + port + '.'); System.out.println("Open your browser and navigate to http://localhost:" + port + '/'); } public static void main(String[] args) { int port; if (args.length > 0) { port = Integer.parseInt(args[0]); } else { port = 8080; } new WebSocketServer(port).run(); } }
/** * Handles handshakes and messages */ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler { private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandler.class); private static final String WEBSOCKET_PATH = "/websocket"; private WebSocketServerHandshaker handshaker; //频道channel private static List<Channel> channels = null; private static ChannelGroup channelG = null; static{ channels = new ArrayList<Channel>(); channelG = new DefaultChannelGroup(); System.out.println("staic..............."); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Object msg = e.getMessage(); if (msg instanceof HttpRequest) { handleHttpRequest(ctx, (HttpRequest) msg); } else if (msg instanceof WebSocketFrame) { handleWebSocketFrame(ctx, (WebSocketFrame) msg); } } /** * 请求分发到页面 * @param ctx * @param req * @throws Exception */ private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception { // Allow only GET methods. if (req.getMethod() != GET) { sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN)); return; } // Send the demo page and favicon.ico if (req.getUri().equals("/")) { HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK); ChannelBuffer content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req)); res.setHeader(CONTENT_TYPE, "text/html; charset=UTF-8"); setContentLength(res, content.readableBytes()); res.setContent(content); sendHttpResponse(ctx, req, res); return; } else if (req.getUri().equals("/favicon.ico")) { HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND); sendHttpResponse(ctx, req, res); return; } // Handshake WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(req), null, false); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) { wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); } else { handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER); } } private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { // Check for closing frame if (frame instanceof CloseWebSocketFrame) { handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame); return; } else if (frame instanceof PingWebSocketFrame) { ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData())); return; } else if (!(frame instanceof TextWebSocketFrame)) { throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass() .getName())); } // Send the uppercase string back. String request = ((TextWebSocketFrame) frame).getText(); if (null != request) { System.out.println(String.format("Channel %s received %s", ctx.getChannel().getId(), request)); if (logger.isDebugEnabled()) { logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request)); } // ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase())); channelG.write(new TextWebSocketFrame(request.toUpperCase())); //循环频道 // System.err.println(channels.size()); // for (int i = 0; i < channels.size(); i++) { // channels.get(i).write(new TextWebSocketFrame(request.toUpperCase())); // } } } private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) { // Generate an error page if response status code is not OK (200). if (res.getStatus().getCode() != 200) { res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8)); setContentLength(res, res.getContent().readableBytes()); } // Send the response and close the connection if necessary. ChannelFuture f = ctx.getChannel().write(res); if (!isKeepAlive(req) || res.getStatus().getCode() != 200) { f.addListener(ChannelFutureListener.CLOSE); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { e.getCause().printStackTrace(); e.getChannel().close(); System.out.println("exceptionCaught============="); } private static String getWebSocketLocation(HttpRequest req) { return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH; } @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // super.channelConnected(ctx, e); // channels.add(e.getChannel()); channelG.add(e.getChannel()); // channelG.addAll(channels); } @Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { super.channelDisconnected(ctx, e); } }
/** * Generates the demo HTML page which is served at http://localhost:8080/ 页面(该页面写在代码的形式输出) */ public final class WebSocketServerIndexPage { private static final String NEWLINE = "\r\n"; public static ChannelBuffer getContent(String webSocketLocation) { return ChannelBuffers.copiedBuffer( "<html><head><title>Web Socket Test</title></head>" + NEWLINE + "<body>" + NEWLINE + "<script type=\"text/javascript\">" + NEWLINE + "var socket;" + NEWLINE + "if (!window.WebSocket) {" + NEWLINE + " window.WebSocket = window.MozWebSocket;" + NEWLINE + "}" + NEWLINE + "if (window.WebSocket) {" + NEWLINE + " socket = new WebSocket(\"" + webSocketLocation + "\");" + NEWLINE + " socket.onmessage = function(event) {" + NEWLINE + " var ta = document.getElementById('responseText');" + NEWLINE + " ta.value = ta.value + '\\n' + event.data" + NEWLINE + " };" + NEWLINE + " socket.onopen = function(event) {" + NEWLINE + " var ta = document.getElementById('responseText');" + NEWLINE + " ta.value = \"Web Socket opened!\";" + NEWLINE + " };" + NEWLINE + " socket.onclose = function(event) {" + NEWLINE + " var ta = document.getElementById('responseText');" + NEWLINE + " ta.value = ta.value + \"Web Socket closed\"; " + NEWLINE + " };" + NEWLINE + "} else {" + NEWLINE + " alert(\"Your browser does not support Web Socket.\");" + NEWLINE + "}" + NEWLINE + NEWLINE + "function send(message) {" + NEWLINE + " if (!window.WebSocket) { return; }" + NEWLINE + " if (socket.readyState == WebSocket.OPEN) {" + NEWLINE + " socket.send(message);" + NEWLINE + " } else {" + NEWLINE + " alert(\"The socket is not open.\");" + NEWLINE + " }" + NEWLINE + "}" + NEWLINE + "</script>" + NEWLINE + "<form onsubmit=\"return false;\">" + NEWLINE + "<input type=\"text\" name=\"message\" value=\"Hello, World!\"/>" + "<input type=\"button\" value=\"Send Web Socket Data\"" + NEWLINE + " onclick=\"send(this.form.message.value)\" />" + NEWLINE + "<h3>Output</h3>" + NEWLINE + "<textarea id=\"responseText\" style=\"width:500px;height:300px;\"></textarea>" + NEWLINE + "</form>" + NEWLINE + "</body>" + NEWLINE + "</html>" + NEWLINE, CharsetUtil.US_ASCII); } private WebSocketServerIndexPage() { // Unused } }
/** */ public class WebSocketServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = pipeline(); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("aggregator", new HttpChunkAggregator(65536)); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("handler", new WebSocketServerHandler()); return pipeline; } }
注:在推前两次请求时会报
java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame
暂末找到原因,不过不影响程序的运行,跟进中......
相关推荐
客户端发送16进制给服务端,并行实现socket通道活动状态...netty作为服务器端如何主动的向传感器发送消息,我尝试当每个传感器连接到netty(TCP/IP)时使用一个map把该channelSocket的id和该channelSocket绑定在一起。
同样,服务器如果需要向客户端推送数据,也需要先序列化protobuf消息,然后通过Netty的writeAndFlush方法发送出去,客户端这边通过protobuf的反序列化机制恢复数据。 总结来说,这个项目实现了C++客户端与Java ...
这通常意味着代码可能包括基础示例,用于演示如何在C#环境中设置Netty客户端和服务器,并实现双向通信,即两个端点都能发送和接收数据。 从文件名称列表来看,我们可以推测项目可能包含以下内容: 1. `UpgradeLog....
通过netty编写文件传输的客户端与服务端,以及协议说明, 通用的netty传输协议 通过该协议进行文件传输 文件传输客户端与服务端 可以根据文件的最后更新时间来增量传输文件 源码开放,通过eclipse或者idea导入代码...
Netty是一个异步事件驱动的网络应用程序框架,它为高性能、高可用性的网络服务器和客户端提供了一种简单易用的方式。本实践将详细介绍如何在Android环境中使用Netty进行客户端和服务端的通信。 首先,我们需要理解...
- 客户端向服务器发送数据,然后接收并打印服务器的回应。 通过以上步骤,我们可以了解Netty的基本使用和工作流程。在实际项目中,Netty的强大功能和灵活性使其成为构建高性能网络应用的理想选择。无论是游戏服务器...
标题中的“Netty实现Java服务端和C#客户端联通”是指使用Netty作为Java服务器框架,与C#客户端(使用DotNetty库)进行通信的一种技术实现。这涉及到跨平台的网络通信,以及两个不同编程语言间的交互。 Netty是Java...
在"基于Java Netty的UDP客户端声呐数据对接"项目中,我们主要关注如何利用Netty处理UDP通信,以及如何解析和封装SCANFISH-II型声呐系统的数据。 UDP(User Datagram Protocol)是一种无连接的传输层协议,它不保证...
这个项目可能包含了使用`LineBasedFrameDecoder`和`DelimiterBasedFrameDecoder`的服务器端和客户端实现,通过这些文件,开发者可以学习如何在实际项目中应用Netty来处理粘包和分包问题。 总之,理解和正确使用...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。整合Spring Boot与Netty,可以利用Spring的便捷性和Netty的高效性来构建实时通信系统,例如基于Socket的服务...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在这个“基于Netty的服务器客户端收发消息代码”中,我们可以看到一个简单的实现,它演示了如何使用Netty进行...
在本场景中,"netty 推送 android客户端" 指的是使用Netty框架实现从服务器向Android客户端推送数据的功能。这个功能的实现通常涉及到以下几个关键知识点: 1. **Netty序列化**: - Netty 提供了多种序列化方式,...
Netty是一个高性能、异步事件驱动的网络应用框架,它为Java开发人员提供了构建高性能、高可用性的网络服务器和客户端的API。这个框架广泛应用于分布式系统、消息中间件、游戏服务器等领域,因其高效和易用性而备受...
综上所述,Spring Boot与Netty的结合使用,能够构建出强大的实时消息推送系统,满足现代Web应用中对于数据实时同步的需求。通过理解并熟练掌握上述知识点,开发者可以创建出高效、可靠的通信平台。
基于Netty实现的MQTT客户端_netty-mqtt-client
分析这个代码,我们可以看到Netty如何创建服务器、设置管道、以及如何定义和使用自定义的解码器和编码器来处理16进制数据。 通过上述步骤,Netty服务器可以轻松地解析16进制数据,从而支持各种网络协议,无论它们是...
在这个示例中,客户端和服务器端通过Netty框架进行通信,实现数据对象的传输。通常,这个过程包括以下步骤: 1. **服务器端启动**:服务器端首先创建一个ServerBootstrap实例,配置EventLoopGroup(通常包含一个...
这个简单的例子展示了Netty的基本用法,包括设置服务器和客户端的Bootstrap、创建自定义的ChannelHandler以及进行数据的读写操作。然而,Netty的强大之处还在于它的高度可扩展性和丰富的功能,如流式API、零拷贝、多...
本教程将详细讲解如何使用Netty实现Websocket服务器以及对应的客户端网页。首先,我们需要理解Netty的核心概念:Channel、EventLoopGroup和Bootstrap。Channel是网络连接的抽象,用于读写数据;EventLoopGroup是一组...
JBoss Netty是一个高性能、异步事件驱动的网络应用程序框架,它为快速开发可维护的高性能协议服务器和客户端提供了丰富的API。本篇文章将深入探讨如何利用JBoss Netty创建高效的Web Service客户端和服务端。 首先,...