赞
踩
1.pom引入依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.70.Final</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
2.application.yml配置
server:
port: 8095
servlet:
context-path: /netty
netty:
url: 0.0.0.0 #0.0.0.0表示绑定任意ip
port: 20004
3.启动类配置
import com.example.demo.server.NioNettyServer; import io.netty.channel.ChannelFuture; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.jms.annotation.EnableJms; import org.springframework.scheduling.annotation.EnableAsync; @EnableAsync @SpringBootApplication public class DemoApplication implements CommandLineRunner { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); context.getBean(NioNettyServer.class).start(); } @Override public void run(String... args) throws Exception { } }
4.创建netty服务
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.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.ipfilter.IpFilterRule; import io.netty.handler.ipfilter.IpFilterRuleType; import io.netty.handler.ipfilter.IpSubnetFilterRule; import io.netty.handler.ipfilter.RuleBasedIpFilter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.net.InetSocketAddress; @Slf4j @Component public class NioNettyServer { @Value("${netty.port}") private int port; @Value("${netty.url}") private String url; private final EventLoopGroup bossGroup = new NioEventLoopGroup(); private final EventLoopGroup workerGroup = new NioEventLoopGroup(); private Channel channel; //把Netty交给spring托管,不然读不到application.yml的值 @Autowired private ClientMessageHandler clientMessageHandler; @Async public void start() { final ClientMessageHandler serverHandler = clientMessageHandler; ChannelFuture f = null; // 接收连接 EventLoopGroup boss = new NioEventLoopGroup(); // 处理信息 EventLoopGroup worker = new NioEventLoopGroup(); try { // 定义server ServerBootstrap serverBootstrap = new ServerBootstrap(); // 添加分组 serverBootstrap.group(bossGroup, workerGroup) // 添加通道设置非阻塞 .channel(NioServerSocketChannel.class) // 服务端可连接队列数量 .option(ChannelOption.SO_BACKLOG, 128) .localAddress(new InetSocketAddress(url,port)) // 开启长连接 .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { // 为监听客户端read/write事件的Channel添加用户自定义的ChannelHandler socketChannel.pipeline().addLast(serverHandler); //--------------------- 以下代码用了设置黑名单,白名单过滤ip,没有需求可以注释掉 (58.61.0.1,16)表示模糊匹配前两位,8表示匹配IP第一位,16表示匹配IP一,二位,以此类推------------------------------------------------------- // 32表示全匹配 //白名单 // IpSubnetFilterRule rule1 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.ACCEPT); //黑名单 // IpSubnetFilterRule rule2 = new IpSubnetFilterRule("127.0.0.1", 32, IpFilterRuleType.REJECT); // IpFilterRule rejectAll = new IpFilterRule() { // @Override // public boolean matches(InetSocketAddress remoteAddress) { // return true; // } // @Override // public IpFilterRuleType ruleType() { // return IpFilterRuleType.REJECT; // } // }; // RuleBasedIpFilter filter = new RuleBasedIpFilter(rule1, rejectAll ); // socketChannel.pipeline().addLast("ipFilter", filter); // socketChannel.pipeline().addLast("encoder", new StringEncoder()); // socketChannel.pipeline().addLast("decoder", new StringDecoder()); //----------------------------------------------------------以上为ip过滤----------------------------------------------------------- } }); // 绑定端口 f = serverBootstrap.bind().sync(); channel = f.channel(); log.info("-------------netty启动成功--------端口{}", port); } catch (Exception e) { log.error("connection error",e.getMessage(), e); } finally { boss.shutdownGracefully(); worker.shutdownGracefully(); } } }
4.创建netty客户端信息接收器
import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import io.netty.channel.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component @Slf4j @ChannelHandler.Sharable public class ClientMessageHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //把数据解析转成字符串 ByteBuf in = (ByteBuf) msg; String str= in.toString(CharsetUtil.UTF_8); log.info("接收到数据: "+str); // 返回请求结果 Channel channel = ctx.channel(); channel.writeAndFlush(JSONUtil.toJsonStr(str)); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { // ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); } //只要Netty抛出错误就会执行,Netty断会开连接会抛出连接超时的错误 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { log.info("关闭通道"); cause.printStackTrace(); ctx.close(); } }
5.启动项目用main方法测试
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1", 20004);
socket.getOutputStream().write("[netty,2022-10-21 14:12:09]".getBytes("UTF-8"));
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。