<!-- netty -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.12.Final</version>
</dependency>
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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class NettyServer {
private static final int port = 9091;
public void run() throws Exception{
//NioEventLoopGroup是用来处理IO操作的多线程事件循环器
EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用来接收进来的连接
EventLoopGroup workerGroup = new NioEventLoopGroup();// 用来处理已经被接收的连接
try{
ServerBootstrap server =new ServerBootstrap();//是一个启动NIO服务的辅助启动类
server.group(bossGroup,workerGroup )
.channel(NioServerSocketChannel.class) // 这里告诉Channel如何接收新的连接
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 自定义处理类
ch.pipeline().addLast(new NettyServerHandler());
}
});
// 具体参数介绍 https://blog.csdn.net/zhousenshan/article/details/72859923
server.option(ChannelOption.SO_BACKLOG,128);
// 保持长连接
server.childOption(ChannelOption.SO_KEEPALIVE, true);
//绑定端口,同步等待成功
ChannelFuture future = server.bind(port).sync();
log.info("服务端启动成功...");
// 监听服务器关闭监听
future.channel().closeFuture().sync();
}finally {
//关闭EventLoopGroup,释放掉所有资源包括创建的线程
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new NettyServer().run();
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
@Slf4j
@Component
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
/**
* 收到数据时调用
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
//传来的消息包装成字节缓冲区
ByteBuf in = (ByteBuf)msg;
int readableBytes = in.readableBytes();
byte[] bytes =new byte[readableBytes];
in.readBytes(bytes);
String str = new String(bytes);
//System.out.print(in.toString(CharsetUtil.UTF_8));
log.info("服务端接受的消息 : " + str);
log.info("服务端接受的消息 : " + msg);
}finally {
// 抛弃收到的数据
ReferenceCountUtil.release(msg);
}
}
/**
* 数据读取完毕事件
* @param ctx
*/
public void channelReadComplete(ChannelHandlerContext ctx){
//数据读取完毕,将信息包装成一个Buffer传递给下一个Handler,Unpooled.copiedBuffer会返回一个Buffer
//调用的是事件处理器的上下文对象的writeAndFlush方法
//意思就是说将 *参数* 传递给了下一个handler
ByteBuf byteBuf = Unpooled.copiedBuffer("Receive the success ", CharsetUtil.UTF_8);
ctx.writeAndFlush(byteBuf);
}
/**
* 异常处理
* @param ctx
* @param cause
*/
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
try{
cause.printStackTrace();
}catch (Exception e){
e.printStackTrace();
log.error("异常.."+e.getMessage());
}finally {
ctx.close();
}
}
/**
* 建立连接时,返回消息
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("连接的客户端地址:" + ctx.channel().remoteAddress());
log.info("连接的客户端ID:" + ctx.channel().id());
ctx.writeAndFlush("client"+ InetAddress.getLocalHost().getHostName() + "success connected! \n");
log.info("connection in .. success");
super.channelActive(ctx);
}
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 自定义处理类
ch.pipeline().addLast(new NettyServerHandler());
}
}
这边我客户端是用stocket 现实的,方便把。 有兴趣的可以把netty 的客户端的实现方式列出来。