netty初学笔记
阻塞与非阻塞
阻塞:阻塞是指调用结果返回之前,当前线程会被挂起。
非阻塞:非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会显式技术阻塞当前线程 。
同步与异步
同步:在c端发出一个功能调用时,在没有得到结果之前,该调用就不返回。
异步::异步的概念和同步相对应。当c端一个异步过程调用发出后,调用者不能立刻得到结果。先返回。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。
BIO、NIO与AIO
BIO:同步阻塞式IO,简单理解:一个线程处理一个连接,发起和处理IO请求都是同步的。
NIO:同步非阻塞IO,简单理解:一个线程处理多个连接,发起IO请求是非阻塞的但处理IO请求是同步的。
AIO:异步非阻塞IO,简单理解:一个有效请求一个线程,发起和处理IO请求都是异步的。
netty使用的是NIO
Springboot整合netty
pom依赖
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.25.Final</version>
</dependency>
##
目录结构
代码
@Component
class WebScoketServer<main> {
private EventLoopGroup mianGroup;
private EventLoopGroup subGroup;
private ServerBootstrap serverBootstrap;
private ChannelFuture channelFuture;
private static class SingletionWSServer {
static final WebScoketServer instance = new WebScoketServer();
}
public static WebScoketServer getInstance() {
return SingletionWSServer.instance;
}
public WebScoketServer() {
mianGroup = new NioEventLoopGroup();
subGroup = new NioEventLoopGroup();
serverBootstrap = new ServerBootstrap();
serverBootstrap.group(mianGroup, subGroup).channel(NioServerSocketChannel.class).childHandler(new WSServerInitialzer());
}
public void start() {
this.channelFuture = serverBootstrap.bind(8088);
System.err.print("netty websocket server 启动完毕");
}
}
public class WSServerInitialzer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline=socketChannel.pipeline();
//websocket基于http协议,所以要有http编解码器
pipeline.addLast(new HttpServerCodec());
//对写大数据流的支持
pipeline.addLast(new ChunkedWriteHandler());
//对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse,1024*64是消息的最大长度
pipeline.addLast(new HttpObjectAggregator(1024*64));
/**
*webcocket服务器处理的协议,用于指定给客户端连接访问的路由:/ws
* 本handler会帮你处理一些繁重的复杂的事
* 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同
*/
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast(new ChatHandler());
}
}
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
// 用于记录和管理所有客户端的channle
private static ChannelGroup clients =
new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)
throws Exception {
// 获取客户端传输过来的消息
String content = msg.text();
System.out.println("接受到的数据:" + content);
clients.writeAndFlush(
new TextWebSocketFrame(
"[服务器在]" + LocalDateTime.now()
+ "接受到消息, 消息为:" + content));
}
/**
* 当客户端连接服务端之后(打开连接)
* 获取客户端的channle,并且放到ChannelGroup中去进行管理
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
clients.add(ctx.channel());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
// 当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel
// clients.remove(ctx.channel());
System.out.println("客户端断开,channle对应的长id为:"
+ ctx.channel().id().asLongText());
System.out.println("客户端断开,channle对应的短id为:"
+ ctx.channel().id().asShortText());
}
}
@Component
public class NettyBooter implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
if(contextRefreshedEvent.getApplicationContext().getParent()==null){//root application context 没有parent,他就是老大.
//需要执行的逻辑代码,当spring容器初始化完成后就会执行该方法。
WebScoketServer.getInstance().start();
}
}
}