Boom
2 years ago
commit
f15dcb5fc1
9 changed files with 466 additions and 0 deletions
@ -0,0 +1,40 @@
|
||||
target/ |
||||
!.mvn/wrapper/maven-wrapper.jar |
||||
!**/src/main/**/target/ |
||||
!**/src/test/**/target/ |
||||
|
||||
### IntelliJ IDEA ### |
||||
.idea/modules.xml |
||||
.idea/jarRepositories.xml |
||||
.idea/compiler.xml |
||||
.idea/libraries/ |
||||
*.iws |
||||
*.iml |
||||
*.ipr |
||||
|
||||
### Eclipse ### |
||||
.apt_generated |
||||
.classpath |
||||
.factorypath |
||||
.project |
||||
.settings |
||||
.springBeans |
||||
.sts4-cache |
||||
|
||||
### NetBeans ### |
||||
/nbproject/private/ |
||||
/nbbuild/ |
||||
/dist/ |
||||
/nbdist/ |
||||
/.nb-gradle/ |
||||
build/ |
||||
!**/src/main/**/build/ |
||||
!**/src/test/**/build/ |
||||
|
||||
### VS Code ### |
||||
.vscode/ |
||||
|
||||
### Mac OS ### |
||||
.DS_Store |
||||
logs |
||||
.idea |
@ -0,0 +1,72 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>com.zsw</groupId> |
||||
<artifactId>netty01</artifactId> |
||||
<version>1.0-SNAPSHOT</version> |
||||
<packaging>jar</packaging> |
||||
|
||||
<name>netty01</name> |
||||
<url>http://maven.apache.org</url> |
||||
|
||||
<properties> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
<maven.compiler.source>1.8</maven.compiler.source> |
||||
<maven.compiler.target>1.8</maven.compiler.target> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>io.netty</groupId> |
||||
<artifactId>netty-all</artifactId> |
||||
<version>4.1.63.Final</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter</artifactId> |
||||
<version>2.7.10</version> |
||||
<scope>compile</scope> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.google.guava/guava --> |
||||
<dependency> |
||||
<groupId>com.google.guava</groupId> |
||||
<artifactId>guava</artifactId> |
||||
<version>31.1-jre</version> |
||||
</dependency> |
||||
|
||||
|
||||
<dependency> |
||||
<groupId>org.projectlombok</groupId> |
||||
<artifactId>lombok</artifactId> |
||||
<optional>true</optional> |
||||
<version>1.18.28</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> |
||||
<dependency> |
||||
<groupId>cn.hutool</groupId> |
||||
<artifactId>hutool-all</artifactId> |
||||
<version>5.8.16</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> |
||||
<dependency> |
||||
<groupId>com.google.code.gson</groupId> |
||||
<artifactId>gson</artifactId> |
||||
<version>2.9.0</version> |
||||
</dependency> |
||||
|
||||
|
||||
<dependency> |
||||
<groupId>junit</groupId> |
||||
<artifactId>junit</artifactId> |
||||
<version>3.8.1</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
|
||||
</project> |
@ -0,0 +1,24 @@
|
||||
package com.zsw; |
||||
|
||||
import com.zsw.starter.Client; |
||||
import com.zsw.starter.Server; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
/** |
||||
* Hello world! |
||||
* |
||||
*/ |
||||
@Slf4j |
||||
public class App |
||||
{ |
||||
public static void main( String[] args ) |
||||
{ |
||||
log.info("hello,world. {}",1); |
||||
System.out.println( "Hello World!" ); |
||||
Server server = new Server(); |
||||
server.run(); |
||||
|
||||
Client client = new Client(); |
||||
client.run(); |
||||
} |
||||
} |
@ -0,0 +1,64 @@
|
||||
package com.zsw.starter; |
||||
|
||||
import cn.hutool.core.thread.ThreadUtil; |
||||
import com.zsw.starter.handler.ClientHandler; |
||||
import io.netty.bootstrap.Bootstrap; |
||||
import io.netty.channel.ChannelFuture; |
||||
import io.netty.channel.ChannelInitializer; |
||||
import io.netty.channel.ChannelOption; |
||||
import io.netty.channel.nio.NioEventLoopGroup; |
||||
import io.netty.channel.socket.SocketChannel; |
||||
import io.netty.channel.socket.nio.NioSocketChannel; |
||||
import io.netty.handler.codec.json.JsonObjectDecoder; |
||||
import io.netty.handler.codec.string.StringEncoder; |
||||
import io.netty.handler.timeout.IdleStateHandler; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
@Slf4j |
||||
public class Client { |
||||
|
||||
private void start(int i) throws InterruptedException { |
||||
NioEventLoopGroup group = new NioEventLoopGroup(); |
||||
Bootstrap bootstrap = new Bootstrap(); |
||||
bootstrap.group(group) |
||||
.channel(NioSocketChannel.class) |
||||
.option(ChannelOption.TCP_NODELAY, true) |
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) |
||||
.handler(new ChannelInitializer<SocketChannel>() { |
||||
protected void initChannel(SocketChannel ch) { |
||||
// 注册名称
|
||||
ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 60, 60, TimeUnit.SECONDS)); |
||||
ch.pipeline().addLast(new JsonObjectDecoder()); |
||||
ch.pipeline().addLast(new StringEncoder()); |
||||
ch.pipeline().addLast(new ClientHandler(i)); |
||||
} |
||||
}); |
||||
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8899); |
||||
channelFuture.sync(); |
||||
channelFuture.channel().closeFuture().sync(); |
||||
} |
||||
|
||||
public void run(){ |
||||
for (int i = 0; i < 10; i++) { |
||||
// try {
|
||||
// Thread.sleep(200);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
int finalI = i; |
||||
ThreadUtil.execAsync(()->{ |
||||
log.info("client:{} ready", finalI); |
||||
try { |
||||
this.start(finalI); |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
}); |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.zsw.starter; |
||||
|
||||
import com.zsw.starter.handler.ServerHandler; |
||||
import io.netty.bootstrap.ServerBootstrap; |
||||
import io.netty.channel.ChannelFuture; |
||||
import io.netty.channel.ChannelInitializer; |
||||
import io.netty.channel.ChannelOption; |
||||
import io.netty.channel.ChannelPipeline; |
||||
import io.netty.channel.nio.NioEventLoopGroup; |
||||
import io.netty.channel.socket.SocketChannel; |
||||
import io.netty.channel.socket.nio.NioChannelOption; |
||||
import io.netty.channel.socket.nio.NioServerSocketChannel; |
||||
import io.netty.handler.codec.json.JsonObjectDecoder; |
||||
import io.netty.handler.codec.string.StringEncoder; |
||||
import io.netty.handler.timeout.IdleStateHandler; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
@Slf4j |
||||
public class Server { |
||||
|
||||
private void start() throws InterruptedException { |
||||
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); |
||||
//new 一个工作线程组
|
||||
NioEventLoopGroup workGroup = new NioEventLoopGroup(200); |
||||
ServerBootstrap bootstrap = new ServerBootstrap() |
||||
.group(bossGroup, workGroup) |
||||
.channel(NioServerSocketChannel.class) |
||||
.childHandler(new ChannelInitializer<SocketChannel>() { |
||||
@Override |
||||
protected void initChannel(SocketChannel socketChannel) throws Exception { |
||||
ChannelPipeline pipline = socketChannel.pipeline(); |
||||
pipline.addLast("heart",new IdleStateHandler(5,5,10, TimeUnit.SECONDS)); |
||||
// pipline.addFirst(new JsonObjectDecoder());
|
||||
pipline.addLast(new StringEncoder()); |
||||
pipline.addLast(new ServerHandler()); |
||||
} |
||||
}) |
||||
.localAddress(8899) |
||||
.option(ChannelOption.SO_BACKLOG, 1024) |
||||
.childOption(NioChannelOption.SO_KEEPALIVE, true); |
||||
ChannelFuture future = bootstrap.bind().sync(); |
||||
log.info("打印服务启动,端口:{} ",8899); |
||||
} |
||||
|
||||
public void run(){ |
||||
try { |
||||
this.start(); |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
package com.zsw.starter.handler; |
||||
|
||||
import io.netty.buffer.ByteBuf; |
||||
import io.netty.channel.ChannelHandlerContext; |
||||
import io.netty.channel.SimpleChannelInboundHandler; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
|
||||
@Slf4j |
||||
public class ClientHandler extends SimpleChannelInboundHandler<ByteBuf> { |
||||
int i ; |
||||
public ClientHandler(int i) { |
||||
this.i = i; |
||||
} |
||||
|
||||
@Override |
||||
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { |
||||
String channelId = channelHandlerContext.channel().id().toString(); |
||||
byte[] bytes = new byte[byteBuf.readableBytes()]; |
||||
byteBuf.getBytes(byteBuf.readerIndex(), bytes); |
||||
String info = new String(bytes, StandardCharsets.UTF_8); |
||||
log.info("info:{}",info); |
||||
} |
||||
|
||||
@Override |
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception { |
||||
super.channelActive(ctx); |
||||
log.info("客户端连接:{}",ctx.channel().id()); |
||||
ctx.writeAndFlush("ctx-"+i); |
||||
} |
||||
} |
@ -0,0 +1,62 @@
|
||||
package com.zsw.starter.handler; |
||||
|
||||
import cn.hutool.core.util.StrUtil; |
||||
import io.netty.buffer.ByteBuf; |
||||
import io.netty.channel.ChannelHandlerContext; |
||||
import io.netty.channel.ChannelId; |
||||
import io.netty.channel.SimpleChannelInboundHandler; |
||||
import lombok.Synchronized; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.io.OutputStream; |
||||
import java.io.OutputStreamWriter; |
||||
import java.net.Socket; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
|
||||
@Slf4j |
||||
public class ServerHandler extends SimpleChannelInboundHandler<ByteBuf> { |
||||
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { |
||||
|
||||
String channelId = channelHandlerContext.channel().id().toString(); |
||||
byte[] bytes = new byte[byteBuf.readableBytes()]; |
||||
byteBuf.getBytes(byteBuf.readerIndex(), bytes); |
||||
String info = new String(bytes, StandardCharsets.UTF_8); |
||||
log.info("channelHandlerContext:{}",channelHandlerContext.channel().id()); |
||||
test(channelHandlerContext.channel().id()); |
||||
|
||||
// Thread.sleep(5000L);
|
||||
Socket socket = new Socket("192.168.10.188", 9100); |
||||
OutputStream socketOut = socket.getOutputStream(); |
||||
OutputStreamWriter writer = new OutputStreamWriter(socketOut, "GBK"); |
||||
socketOut.write(27); |
||||
socketOut.write(27); |
||||
String str = StrUtil.format("ctx:{},text:{}\n",channelHandlerContext.channel().id(),info); |
||||
writer.write(str); |
||||
writer.flush(); |
||||
|
||||
writer.write(27); |
||||
writer.write(100); |
||||
writer.write(4); |
||||
writer.write(10); |
||||
writer.flush(); |
||||
|
||||
writer.write(0x1D); |
||||
writer.write("V"); |
||||
writer.write(48); |
||||
writer.write(0); |
||||
writer.flush(); |
||||
|
||||
log.info("停止5秒后完成"); |
||||
socket.close(); |
||||
writer.close(); |
||||
socketOut.close(); |
||||
} |
||||
|
||||
|
||||
private synchronized void test(ChannelId id){ |
||||
log.info("测试同步开始...{}",id); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<configuration debug="false" scan="false"> |
||||
<property name="log.path" value="logs"/> |
||||
|
||||
<!-- <!– 彩色日志格式 –>--> |
||||
<!-- <property name="CONSOLE_LOG_PATTERN"--> |
||||
<!-- value="%clr([${spring.application.name}:${server.port}:%X{tenant}:%X{userid}]) %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>--> |
||||
|
||||
<!-- <!– 普通日志格式 –>--> |
||||
<!-- <property name="CONSOLE_LOG_PATTERN_NO_COLOR"--> |
||||
<!-- value="[${spring.application.name}:${server.port}:%X{tenant}:%X{userid}] %d{yyyy-MM-dd HH:mm:ss.SSS}[%5p] ${PID} [%X{trace}] [%t:%r] [%logger{50}.%M:%L] %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" />--> |
||||
|
||||
<property name="CONSOLE_LOG_PATTERN" |
||||
value=" %clr(%d{yyyy-MM-dd HH:mm:ss:SSS}) %clr(){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/> |
||||
|
||||
<!-- 普通日志格式 --> |
||||
<property name="CONSOLE_LOG_PATTERN_NO_COLOR" |
||||
value=" %d{yyyy-MM-dd HH:mm:ss}[%5p] [%X{trace}] [%t:%r] [%logger{50}.%M:%L] %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}" /> |
||||
|
||||
|
||||
<!-- 彩色日志依赖的渲染类 --> |
||||
<conversionRule conversionWord="clr" |
||||
converterClass="org.springframework.boot.logging.logback.ColorConverter"/> |
||||
<conversionRule conversionWord="wex" |
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/> |
||||
<conversionRule conversionWord="wEx" |
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/> |
||||
<!-- <conversionRule conversionWord="traceId" converterClass="com.zsw.pos.common.converter.ZswLogPrefixConverter"/>--> |
||||
|
||||
<!-- Console log output --> |
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
||||
<encoder> |
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern> |
||||
</encoder> |
||||
</appender> |
||||
|
||||
<!-- Log file info output --> |
||||
<appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
<file>${log.path}/info.log</file> |
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
||||
<fileNamePattern>${log.path}/%d{yyyy-MM, aux}/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> |
||||
<maxFileSize>50MB</maxFileSize> |
||||
<maxHistory>30</maxHistory> |
||||
</rollingPolicy> |
||||
<encoder> |
||||
<pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern> |
||||
<charset>UTF-8</charset> |
||||
</encoder> |
||||
</appender> |
||||
|
||||
<!-- Log file error output --> |
||||
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
||||
<file>${log.path}/error.log</file> |
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
||||
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> |
||||
<maxFileSize>50MB</maxFileSize> |
||||
<maxHistory>30</maxHistory> |
||||
</rollingPolicy> |
||||
<encoder> |
||||
<pattern>${CONSOLE_LOG_PATTERN_NO_COLOR}</pattern> |
||||
<charset>UTF-8</charset> |
||||
</encoder> |
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> |
||||
<level>ERROR</level> |
||||
</filter> |
||||
</appender> |
||||
|
||||
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> |
||||
<root level="INFO"> |
||||
<appender-ref ref="console"/> |
||||
<appender-ref ref="error"/> |
||||
<appender-ref ref="info"/> |
||||
</root> |
||||
|
||||
<!-- 服务日志 --> |
||||
<logger name="root" level="info" /> |
||||
|
||||
|
||||
</configuration> |
@ -0,0 +1,38 @@
|
||||
package com.zsw; |
||||
|
||||
import junit.framework.Test; |
||||
import junit.framework.TestCase; |
||||
import junit.framework.TestSuite; |
||||
|
||||
/** |
||||
* Unit test for simple App. |
||||
*/ |
||||
public class AppTest |
||||
extends TestCase |
||||
{ |
||||
/** |
||||
* Create the test case |
||||
* |
||||
* @param testName name of the test case |
||||
*/ |
||||
public AppTest( String testName ) |
||||
{ |
||||
super( testName ); |
||||
} |
||||
|
||||
/** |
||||
* @return the suite of tests being tested |
||||
*/ |
||||
public static Test suite() |
||||
{ |
||||
return new TestSuite( AppTest.class ); |
||||
} |
||||
|
||||
/** |
||||
* Rigourous Test :-) |
||||
*/ |
||||
public void testApp() |
||||
{ |
||||
assertTrue( true ); |
||||
} |
||||
} |
Loading…
Reference in new issue