channelHandlerContext.writeAndFlush(new TextWebSocketFrame("服务器时间: " + LocalDateTime.now() + " : " + textWebSocketFrame.text()));
}
/**
-
客户端连接的时候触发
-
@param ctx
-
@throws Exception
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
// LongText() 唯一的 ShortText() 不唯一
System.out.println(“handlerAdded:” + ctx.channel().id().asLongText());
System.out.println(“handlerAdded:” + ctx.channel().id().asShortText());
}
/**
-
客户端断开连接的时候触发
-
@param ctx
-
@throws Exception
*/
@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();
}
}
2.2 服务端
服务端代码在原有的基础上需要转换相关的协议,具体如下:
package com.dpb.netty.websocket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import java.net.ServerSocket;
/**
-
@program: netty4demo
-
@description: 基于WebSocket协议的服务端
-
@author: 波波烤鸭
-
@create: 2019-12-30 22:31
*/
public class SocketServerDemo {
public static void main(String[] args) throws Exception {
// 1.创建对应的EventLoopGroup对象
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
try{
bootstrap.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// websocket 相关的配置
ChannelPipeline pipeline = socketChannel.pipeline();
//因为基于http协议,使用http的编码和解码器
pipeline.addLast(new HttpServerCodec());
//是以块方式写,添加ChunkedWriteHandler处理器
pipeline.addLast(new ChunkedWriteHandler());
/*
说明
-
http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合
-
这就就是为什么,当浏览器发送大量数据时,就会发出多次http请求
*/
pipeline.addLast(new HttpObjectAggregator(8192));
/*
说明
-
对应websocket ,它的数据是以 帧(frame) 形式传递
-
可以看到WebSocketFrame 下面有六个子类
-
浏览器请求时 ws://localhost:8888/hello 表示请求的uri
-
WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 , 保持长连接
-
是通过一个 状态码 101
*/
pipeline.addLast(new WebSocketServerProtocolHandler(“/hello”));
// 自定义handler,处理业务逻辑
pipeline.addLast(new SocketServerHandler());
}
});
System.out.println(“服务启动了…”);
ChannelFuture future = bootstrap.bind(8888).sync();
future.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
2.3 客户端实现
在客户端中我们就简单的实现一个HTML页面,在其中发送websocket协议相关的请求,然后接受相关的消息,如下,注意注释