<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.42.Final</version>
</dependency>
package com.etc.websocket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
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;
public class MyServer {
public static void main(String[] args) throws InterruptedException {
// 创建2GE GROUp bossGroup wordGroup 线程组
// 默认 cpu 核数 * 2
EventLoopGroup bossGroup = new NioEventLoopGroup(1);// 处理连接
EventLoopGroup wordGroup = new NioEventLoopGroup();// 真正和客户端进行业务处理的。 就交给了wordGroup
//启动服务端
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, wordGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 因为基于http协议 使用http编码器和解码器
pipeline.addLast(new HttpServerCodec());
// 以快的这种方式进行写入
pipeline.addLast(new ChunkedWriteHandler());
/**
* http 数据在传输过程中是分段的. 就是可以将多个进行聚合
* 当浏览器发送大量数据. 就会发送多次http请求
*/
pipeline.addLast(new HttpObjectAggregator(8192));
/**
* 对应的websocket 他的数据一个帧来发送
* 浏览器的请求的地址 ws://localhost:7000/hello 这个是url
*/
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
pipeline.addLast(new MyTextWebSocketHanlder());
}
});
ChannelFuture sync = bootstrap.bind(7000).sync();
sync.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()){
System.out.println("websocket服务启动成功端口7000");
}else {
System.out.println("ebsocket服务启动成功失败");
}
}
});
sync.channel().closeFuture().sync();
}
}
package com.etc.websocket;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.time.LocalDateTime;
/**
* @Author kalista
* @Description
* @Date 2020/9/7 14:34
**/
public class MyTextWebSocketHanlder extends SimpleChannelInboundHandler<TextWebSocketFrame> {
/**
* 服务器收到消息
* @param ctx
* @param msg
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("服务器收到消息了:" + msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:" + LocalDateTime.now() + msg.text()));
}
/**
* 当web客户端连接后 触发方法
* @param ctx
* @throws Exception
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
//id 表示唯一的值,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("有个连接断开:" + ctx.channel().id().asLongText());
}
/**
* 发送异常
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("异常:" + cause.getMessage());
ctx.close();
}
}