艺术网站定制/怎么做网站宣传
由于http协议有一个缺陷:通信只能由客户端发起。如果服务器有连续的状态变化,客户端要获知只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。
而websocket就这样应用而生。
浏览器与服务器之间的长连接,是websocket的支持。WebSocket是一种在单个TCP连接上进行全双工通信的协议。而netty他就对websocket通信做了支持。
websocket除了上面的支持,还有一些其他的特点:
(1)建立在 TCP 协议之上。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,二进制数据。
(5)客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
下面我用netty对websocket的支持来实现一个完整了实现一个在线聊天功能:
服务器端的代码实现:
package com.zhurong.netty.test5;import com.zhurong.netty.test4.NettyServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;import java.net.InetSocketAddress;/*** Description:* User: zhurong* Date: 2018-09-24 23:17*/
public class NettyWebSocketServer {public static void main(String[] args) {//接收连接EventLoopGroup bossGroup = new NioEventLoopGroup();//连接发送给workEventLoopGroup workerGroup = new NioEventLoopGroup();try {System.out.println("服务器启动成功!");ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new WebSocketChannelInitalizer());ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8000)).sync();channelFuture.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}}
package com.zhurong.netty.test5;import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;/*** Description:* User: zhurong* Date: 2018-09-24 11:05*/
public class WebSocketChannelInitalizer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new HttpServerCodec());pipeline.addLast(new ChunkedWriteHandler());pipeline.addLast(new HttpObjectAggregator(8192));pipeline.addLast(new WebSocketServerProtocolHandler("/test"));pipeline.addLast(new WebSockethandler());}
}
package com.zhurong.netty.test5;import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.EventExecutorGroup;import java.util.Date;/*** Description:* User: zhurong* Date: 2018-09-24 11:15*/
public class WebSockethandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {System.out.println("收到浏览器的消息:"+ msg.text());ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器返回消息:" + new Date()));}@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {System.out.println("handlerAdded");}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {System.out.println("handlerRemoved");}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("exceptionCaught");}
}
webapp端的代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>webSocketTest客户端</title>
</head>
<script type="text/javascript">var webSocket;if(window.WebSocket){webSocket = new WebSocket("ws://localhost:8000/test");//客户端收到服务器的方法,这个方法就会被回调webSocket.onmessage = function (ev) {var contents = document.getElementById("responseText");contents.value = contents.value +"\n"+ ev.data;}webSocket.onopen = function (ev) {var contents = document.getElementById("responseText");contents.value = "与服务器端的websocket连接建立";}webSocket.onclose = function (ev) {var contents = document.getElementById("responseText");contents.value = contents.value +"\n"+ "与服务器端的websocket连接断开";}}else{alert("该环境不支持websocket")}function sendMessage() {if(window.webSocket){if(webSocket.readyState == WebSocket.OPEN){var contents = document.getElementById("message").value;webSocket.send(contents);}else{alert("与服务器连接尚未建立")}}}
</script>
<body><form onsubmit="return false;"><h4>客户端输入:</h4><textarea id = "message" name="message" style="width: 200px;height: 100px"></textarea><br/><input type="button" value="发送到服务器" onclick="sendMessage()"><h4>服务器返回消息:</h4><textarea id = "responseText" name="message" style="width: 200px;height: 100px"></textarea><br/><input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="clear data"></form>
</body>
</html>
服务器输出:
这就是一个完整的websocket功能,当然我们其实客户端直接使用浏览器http就可以了,这样更方便。