WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信--允许服务器主动发送信息给客户端.
今天我们来看一些netty的一种长连接的通信方式-WebSocket通信
首先我们的服务器代码为:
package netty.Demo04WebSocket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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;
public class MyServer {
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup work = new NioEventLoopGroup();
NioEventLoopGroup boss = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, work).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new MyInittializer());
ChannelFuture future = bootstrap.bind(8899).sync();
future.channel().closeFuture().sync();
}finally {
work.shutdownGracefully();
boss.shutdownGracefully();
}
}
}
ChannelPipeline管道添加对应的handler:
package netty.Demo04WebSocket;
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;
public class MyInittializer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline channelPipeline= ch.pipeline();
channelPipeline.addLast(new HttpServerCodec());
channelPipeline.addLast(new ChunkedWriteHandler());
channelPipeline.addLast(new HttpObjectAggregator(9012));
channelPipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
channelPipeline.addLast(new TestWebSocketHandler());
}
}
package netty.Demo04WebSocket;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.util.Date;
public class TestWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("来自客户端的消息"+msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:"+ new Date()));
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded"+ctx.channel().id().asLongText());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerRemoved"+ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("异常发生");
ctx.close();
}
}
接下来是我们的客户端 这里我们的客户端用web来体现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
var socket;
if(window.WebSocket){
socket=new WebSocket("ws://127.0.0.1:8899/ws");
socket.onmessage=function(event){
var ta=document.getElementById('responseText');
ta.value=ta.value+"\n"+event.data;
}
socket.onopen=function(event){
var ta=document.getElementById('responseText');
ta.value="链接开启";
}
socket.onclose=function(event){
var ta=document.getElementById('responseText');
ta.value="链接断开";
}
}else{
alert("浏览器不支持webSocket");
}
function send(message){
if(!window.WebSocket){
return;
}
if(socket.readyState == WebSocket.OPEN){
socket.send(message);
}else{
alert("连接尚未开启");
}
}
</script>
<form onsubmit="return false;">
<textarea name="message" style="width:400px;height:200px"></textarea>
<input type="button" value="发送数据" onclick="send(this.form.message.value)">
<h3>服务器输出:</h3>
<textarea id="responseText" style="width:400px; height:300px;"></textarea>
<input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="清空类容">
</form>>
</body>
</html>
我们运行html
可以看到 我们已经连接上服务器 刷新和发送数据都会得到对应的相应