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