Initial commit
commit
ea5bab62c6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,2 @@
|
|||
#Thu Dec 13 11:30:27 CST 2018
|
||||
gradle.version=4.8
|
||||
Binary file not shown.
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel>
|
||||
<module name="jieling-server_main" target="1.8" />
|
||||
<module name="jieling-server_test" target="1.8" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/common" />
|
||||
<option value="$PROJECT_DIR$/hotfix" />
|
||||
<option value="$PROJECT_DIR$/netty" />
|
||||
<option value="$PROJECT_DIR$/serverlogic" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="useAutoImport" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url "http://repo.spring.io/libs-release" }
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.4.RELEASE")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group 'com.ljsd'
|
||||
version '1.0.0-SNAPSHOT'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
|
||||
}
|
||||
|
||||
jar {
|
||||
baseName = 'common'
|
||||
version = '1.0.0'
|
||||
manifest {
|
||||
attributes 'Main-Class': 'com.ljsd.jieling.CommonApplication'
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: com.ljsd.jieling.CommonApplication
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<configuration scan="true" scanPeriod="60 seconds">
|
||||
<contextName>Jieling_Logging</contextName>
|
||||
|
||||
<property name="tip" value="INFO"/>
|
||||
|
||||
<!-- 定义日志文件 输入位置 -->
|
||||
<property name="log_dir" value="/data/logs"/>
|
||||
<!-- 日志最大的历史 30天 -->
|
||||
<property name="maxHistory" value="30"/>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder charset="UTF-8">
|
||||
<pattern>[%level] - %d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %logger{0}#%line - ${tip}:%msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>ACCEPT</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!--<Encoding>UTF-8</Encoding>-->
|
||||
<!-- 过滤器,只记录WARN级别的日志 -->
|
||||
<encoder charset="UTF-8">
|
||||
<pattern>[%level] - %d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %logger{0}#%line - ${tip}:%msg%n</pattern>
|
||||
</encoder>
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>-->
|
||||
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!--日志输出位置 可相对、和绝对路径 -->
|
||||
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/corelog%i.log</fileNamePattern>
|
||||
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
|
||||
则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
|
||||
<maxHistory>${maxHistory}</maxHistory>
|
||||
<maxFileSize>200MB</maxFileSize>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>
|
||||
<minIndex>1</minIndex>
|
||||
<maxIndex>3</maxIndex>
|
||||
</rollingPolicy> -->
|
||||
<!-- 查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>5KB</maxFileSize>
|
||||
</triggeringPolicy>-->
|
||||
</appender>
|
||||
|
||||
|
||||
<!--
|
||||
<appender name="AllLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>log/all/%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>[%level] - %d{yyyy-MM-dd- HH:mm:ss.SSS} - ${tip}:%msg%n</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
-->
|
||||
|
||||
|
||||
<!-- ERROR级别日志 -->
|
||||
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->
|
||||
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!--<Encoding>UTF-8</Encoding>-->
|
||||
<!-- 过滤器,只记录WARN级别的日志 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!--日志输出位置 可相对、和绝对路径 -->
|
||||
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/error-log.log</fileNamePattern>
|
||||
<!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,
|
||||
则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->
|
||||
<maxHistory>${maxHistory}</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>
|
||||
<minIndex>1</minIndex>
|
||||
<maxIndex>3</maxIndex>
|
||||
</rollingPolicy> -->
|
||||
<!-- 查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>5MB</maxFileSize>
|
||||
</triggeringPolicy> -->
|
||||
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
<logger name="org.springframework" level="INFO"/>
|
||||
|
||||
|
||||
|
||||
<root level="INFO">
|
||||
<!-- 控制台输出 -->
|
||||
<appender-ref ref="console"/>
|
||||
|
||||
<appender-ref ref="file_console"/>
|
||||
|
||||
<!-- 文件输出 -->
|
||||
<!--<appender-ref ref="AllLog" />-->
|
||||
<appender-ref ref="ERROR"/>
|
||||
|
||||
<!--<appender-ref ref="TRACE" />-->
|
||||
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
#Mon Dec 17 14:08:44 CST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group 'com.ljsd'
|
||||
version '1.0.0-SNAPSHOT'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest{
|
||||
attributes 'Manifest-Version':'1.0'
|
||||
attributes 'Premain-Class':'com.ljsd.jieling.hotfix.JavaAgent'
|
||||
attributes 'Agent-Class':'com.ljsd.jieling.hotfix.JavaAgent'
|
||||
attributes 'Can-Retransform-Classes':true
|
||||
attributes 'Can-Redefine-Classes':true
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
Manifest-Version: 1.0
|
||||
Premain-Class: com.ljsd.jieling.hotfix.JavaAgent
|
||||
Agent-Class: com.ljsd.jieling.hotfix.JavaAgent
|
||||
Can-Redefine-Classes: true
|
||||
Can-Retransform-Classes: true
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
package com.ljsd.jieling.hotfix;
|
||||
|
||||
public class DynamicClassLoader extends ClassLoader {
|
||||
public Class<?> findClass(byte[] b) throws ClassNotFoundException {
|
||||
|
||||
return defineClass(null, b, 0, b.length);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.ljsd.jieling.hotfix;
|
||||
|
||||
public class HotFixApplication {
|
||||
|
||||
public static void main(String[] arg){
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package com.ljsd.jieling.hotfix;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.instrument.ClassDefinition;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class JavaAgent {
|
||||
private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
|
||||
private static final Object object = new Object();
|
||||
private static String logFileName = "hotfix.log";
|
||||
|
||||
private static SimpleDateFormat getDateFormat(String pattern)
|
||||
throws RuntimeException {
|
||||
SimpleDateFormat dateFormat = threadLocal.get();
|
||||
if (dateFormat == null) {
|
||||
synchronized (object) {
|
||||
dateFormat = new SimpleDateFormat(pattern);
|
||||
dateFormat.setLenient(false);
|
||||
threadLocal.set(dateFormat);
|
||||
}
|
||||
}
|
||||
dateFormat.applyPattern(pattern);
|
||||
return dateFormat;
|
||||
}
|
||||
|
||||
public static String getStrDateYMD() {
|
||||
Date currentTime = new Date();
|
||||
SimpleDateFormat formatter = getDateFormat("yyyyMMdd");
|
||||
String dateString = formatter.format(currentTime);
|
||||
return dateString;
|
||||
}
|
||||
|
||||
public static String getStrDateYMDHMS() {
|
||||
Date currentTime = new Date();
|
||||
SimpleDateFormat formatter = getDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String dateString = formatter.format(currentTime);
|
||||
return dateString;
|
||||
}
|
||||
|
||||
private static void writeLog(Exception e){
|
||||
try {
|
||||
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
|
||||
File file = new File(fname);
|
||||
OutputStream fos=new FileOutputStream(file, true);
|
||||
PrintStream out = new PrintStream(fos);
|
||||
writeLog(e.getMessage());
|
||||
e.printStackTrace(out);
|
||||
out.close();
|
||||
} catch(Exception e1){
|
||||
e.printStackTrace();
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
private static void writeLog(String line){
|
||||
try {
|
||||
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
|
||||
File file = new File(fname);
|
||||
OutputStream fos=new FileOutputStream(file, true);
|
||||
PrintStream out = new PrintStream(fos);
|
||||
line = "[" + getStrDateYMDHMS() + "][" + Thread.currentThread().getId() + "]:" + line + "\n";
|
||||
out.print(line);
|
||||
out.close();
|
||||
} catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//该方法支持在JVM 启动后再启动代理,对应清单的Agent-Class:属性
|
||||
public static void agentmain(String args,Instrumentation inst){
|
||||
try{
|
||||
writeLog("args=:[" + args + "]");
|
||||
File f = new File(args);
|
||||
byte[] targetClassFile = new byte[(int)f.length()];
|
||||
DataInputStream dis = new DataInputStream(new FileInputStream(f));
|
||||
dis.readFully(targetClassFile);
|
||||
dis.close();
|
||||
|
||||
DynamicClassLoader myLoader = new DynamicClassLoader();
|
||||
Class targetClazz = myLoader.findClass(targetClassFile);
|
||||
writeLog("class name is:["+targetClazz.getName() + "]");
|
||||
|
||||
Class<?> clz = Class.forName(targetClazz.getName());
|
||||
writeLog("clz-->Class.forName:(\""+targetClazz.getName() + "\")");
|
||||
|
||||
ClassDefinition clazzDef = new ClassDefinition(clz, targetClassFile);
|
||||
writeLog("ClassDefinition");
|
||||
|
||||
inst.redefineClasses(clazzDef);
|
||||
writeLog("redefineClasses "+args+" finish!");
|
||||
|
||||
}catch(Exception e){
|
||||
writeLog(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group 'com.ljsd'
|
||||
version '1.0.0-SNAPSHOT'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
|
||||
compile("org.javassist:javassist:3.18.2-GA")
|
||||
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
|
||||
compile("io.netty:netty-all:4.0.21.Final")
|
||||
compile("com.google.protobuf:protobuf-java:2.5.0")
|
||||
compile 'com.google.guava:guava:23.5-android'
|
||||
}
|
||||
|
||||
jar {
|
||||
baseName = 'netty'
|
||||
version = '1.0.0'
|
||||
manifest {
|
||||
attributes 'Main-Class': 'com.ljsd.jieling.NettyApplication'
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: com.ljsd.jieling.NettyApplication
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,8 @@
|
|||
package com.ljsd.jieling;
|
||||
|
||||
public class NettyApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("netty server ...");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package com.ljsd.jieling.netty;
|
||||
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class NettyGameSession implements GameSession {
|
||||
|
||||
protected Logger logger = LoggerFactory.getLogger(NettyGameSession.class);
|
||||
|
||||
private int uid;
|
||||
private int areaId;
|
||||
private int offlineType; // 0:正常下线,1:被踢下线
|
||||
private long userLoginTime ;
|
||||
|
||||
private volatile ChannelHandlerContext ctx;
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return (this.ctx != null) && (this.ctx.channel().isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object msg) {
|
||||
ChannelHandlerContext localCtx = this.ctx;
|
||||
if ((localCtx != null) && (localCtx.channel() != null) && (localCtx.channel().isOpen())
|
||||
&& (localCtx.channel().isActive()) && (localCtx.channel().isWritable())) {
|
||||
localCtx.write(msg).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
} else {
|
||||
logger.info("write,uid=>{}, write fail,localCtx={}",uid, localCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeAndFlush(Object msg) {
|
||||
ChannelHandlerContext localCtx = this.ctx;
|
||||
if ((localCtx != null) && (localCtx.channel() != null) && (localCtx.channel().isOpen())
|
||||
&& (localCtx.channel().isActive()) && (localCtx.channel().isWritable())) {
|
||||
localCtx.writeAndFlush(msg).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
} else {
|
||||
logger.info("writeAndFlush, uid=>{},writeAndFlush fail, localCtx is {}", uid, localCtx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.ctx != null) {
|
||||
this.ctx.channel().close();
|
||||
}
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
if ((this.ctx != null) && (this.ctx.channel() != null)) {
|
||||
String ip = this.ctx.channel().remoteAddress().toString();
|
||||
if (!ip.equals("")) {
|
||||
ip = ip.substring(1, ip.length() - 6);
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(int uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public int getAreaId() {
|
||||
return areaId;
|
||||
}
|
||||
|
||||
public void setAreaId(int areaId) {
|
||||
this.areaId = areaId;
|
||||
}
|
||||
|
||||
public ChannelHandlerContext getCtx() {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
public void setCtx(ChannelHandlerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public int getOfflineType() {
|
||||
return offlineType;
|
||||
}
|
||||
|
||||
public void setOfflineType(int offlineType) {
|
||||
this.offlineType = offlineType;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public long getUserLoginTime() {
|
||||
return userLoginTime;
|
||||
}
|
||||
|
||||
public void setUserLoginTime(long userLoginTime) {
|
||||
this.userLoginTime = userLoginTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.ljsd.jieling.netty;
|
||||
|
||||
public class PackageConstant {
|
||||
public static final int LENGTH_FIELD_LEN = 2; //网络包的前两个字节是有效数据的长度
|
||||
public static final int UID_FIELD_LEN = 4; //从其他服务器回包到gateway时,长度后的四个字节是玩家ID
|
||||
public static final int MSG_ID_FIELD_LEN = 4; // 跟网络消息的消息号
|
||||
public static final int RESULT_LEN = 4;//请求结果
|
||||
public static final int TOKEN_LEN = 4;//token长度
|
||||
public static final int INDEX_FIELD_LEN = 4;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BaseDecoder extends ByteToMessageDecoder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BaseDecoder.class);
|
||||
|
||||
public BaseDecoder(){
|
||||
}
|
||||
public short readLean(ByteBuf in){
|
||||
in.markReaderIndex();
|
||||
final byte[] buf = new byte[2];
|
||||
for (int i = 0; i < buf.length; i ++) {
|
||||
if (!in.isReadable()) {
|
||||
in.resetReaderIndex();
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[i] = in.readByte();
|
||||
}
|
||||
int length = Tea.byteToShort(buf, 0);
|
||||
|
||||
return (short) length;
|
||||
}
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ByteBufDecoder extends BaseDecoder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ByteBufDecoder.class);
|
||||
|
||||
public ByteBufDecoder() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
String secret_key = "";
|
||||
try {
|
||||
int length = readLean(in);
|
||||
|
||||
int encodeLen = (length +7) / 8 * 8;
|
||||
if(length == 0){
|
||||
LOGGER.debug("decode->receive empty heartbeat parackage");
|
||||
return;
|
||||
}
|
||||
if (in.readableBytes() < encodeLen){
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
} else {
|
||||
ByteBuf message = in.readBytes(encodeLen);
|
||||
|
||||
int[] secretKey = Tea.KEY;
|
||||
byte[] packetNetData = Tea.decrypt2(message.array(), length,0, secretKey);
|
||||
out.add(packetNetData);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("decode->secret_key={},emsg={}", secret_key, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class ByteBufEncoder extends MessageToByteEncoder<byte[]> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ByteBufDecoder.class);
|
||||
|
||||
public ByteBufEncoder(){
|
||||
}
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) {
|
||||
try {
|
||||
//不加密
|
||||
// out.writeShort((short) msg.length);
|
||||
out.writeBytes(msg, 0, msg.length);
|
||||
} catch (Exception e){
|
||||
LOGGER.error("encode->emsg={}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
public class ClientDate {
|
||||
//包长2 uid 4 msgid 4 result 4 index4
|
||||
private byte[] clientDate;
|
||||
|
||||
public int getMsgId() {
|
||||
return Tea.byteToInt(clientDate, 4);
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
return Tea.byteToInt(clientDate, 0);
|
||||
}
|
||||
|
||||
public int getResult() {
|
||||
return Tea.byteToInt(clientDate, 8);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return Tea.byteToInt(clientDate, 12);
|
||||
}
|
||||
|
||||
/**
|
||||
* 只获取协议信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public byte[] parseProtoNetData() {
|
||||
byte[] data = new byte[clientDate.length - 16];
|
||||
System.arraycopy(clientDate, 16, data, 0, data.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getClientDate() {
|
||||
return clientDate;
|
||||
}
|
||||
|
||||
|
||||
public void setClientDate(byte[] clientDate) {
|
||||
this.clientDate = clientDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import com.ljsd.jieling.tools.DESHelper;
|
||||
import com.ljsd.jieling.tools.Utils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sun.misc.BASE64Decoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 消息解码
|
||||
* 接收到的消息结构为: 消息长度(int) + GameMessage
|
||||
* 解码时 获取前4个字节,转成int获得消息长度,根据消息长度获取具体消息
|
||||
* 此类为Sharable,因为他保持一个连接通道队列,将来可通过此队列发送消息广播
|
||||
*/
|
||||
|
||||
public class Int32FrameDecoder extends ByteToMessageDecoder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Int32FrameDecoder.class);
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
// LOGGER.info("receieve the pack");
|
||||
String secret_key = "";
|
||||
try {
|
||||
in.markReaderIndex();
|
||||
final byte[] buf = new byte[4];
|
||||
for (int i = 0; i < buf.length; i ++) {
|
||||
if (!in.isReadable()) {
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
buf[i] = in.readByte();
|
||||
}
|
||||
int length = Utils.bytesToInt(buf, 0);
|
||||
if (in.readableBytes() < length){
|
||||
in.resetReaderIndex();
|
||||
// LOGGER.info("receieve fail pack");
|
||||
return;
|
||||
}else{
|
||||
ByteBuf message = in.readBytes(length);
|
||||
|
||||
secret_key = ctx.channel().attr(DESHelper.LOGIN_ENCRYPTION_KEY).get();
|
||||
byte[] key = null;
|
||||
if (secret_key == null || secret_key.equals("")){
|
||||
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
|
||||
}else {
|
||||
key = new BASE64Decoder().decodeBuffer(secret_key);
|
||||
}
|
||||
|
||||
byte[] decodeMsg = null;
|
||||
try {
|
||||
decodeMsg = DESHelper.des3DecodeCBC(key, DESHelper.keyiv, message.array());
|
||||
}catch (Exception e){
|
||||
LOGGER.error("decode->secret_key={},msg={}", secret_key, e.getMessage(), e);
|
||||
decodeMsg = DESHelper.des3DecodeCBC(new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY), DESHelper.keyiv, message.array());
|
||||
}
|
||||
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(decodeMsg);
|
||||
|
||||
out.add(byteBuf);
|
||||
return;
|
||||
}
|
||||
}catch (Exception e){
|
||||
LOGGER.error("decode->secret_key={},msg={}", secret_key, e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
||||
// Couldn't find the byte whose MSB is off.
|
||||
// throw new CorruptedFrameException("length wider than 32-bit");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import com.ljsd.jieling.tools.DESHelper;
|
||||
import com.ljsd.jieling.tools.Utils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import sun.misc.BASE64Decoder;
|
||||
|
||||
/**
|
||||
*
|
||||
* 在发送消息到客户端时,在消息前面添加消息长度字段(4字节)
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class Int32LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
|
||||
String secret_key = ctx.channel().attr(DESHelper.LOGIN_ENCRYPTION_KEY).get();
|
||||
String new_Secret_key = ctx.channel().attr(DESHelper.IS_NEW_KEY).getAndRemove();
|
||||
byte[] key = null;
|
||||
if (secret_key == null || secret_key.equals("")){
|
||||
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
|
||||
// LOGGER.info("encode loginEncryptionKey..."+DESHelper.SECRET_KEY);
|
||||
}else {
|
||||
if (new_Secret_key!=null){
|
||||
key = new BASE64Decoder().decodeBuffer(DESHelper.SECRET_KEY);
|
||||
// LOGGER.info("###encode loginEncryptionKey..."+DESHelper.SECRET_KEY);
|
||||
}else {
|
||||
key = new BASE64Decoder().decodeBuffer(secret_key);
|
||||
// LOGGER.info("encode loginEncryptionKey..."+secret_key);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] encodeMsg = DESHelper.des3EncodeCBC(key, DESHelper.keyiv, msg.array());
|
||||
ByteBuf byteBuf = Unpooled.wrappedBuffer(encodeMsg);
|
||||
|
||||
int bodyLen = byteBuf.readableBytes();
|
||||
int headerLen = 4;
|
||||
out.ensureWritable(headerLen + bodyLen);
|
||||
|
||||
byte[] headerByte = Utils.intToBytes(bodyLen);
|
||||
|
||||
out.writeBytes(headerByte, 0, headerLen);
|
||||
out.writeBytes(byteBuf, byteBuf.readerIndex(), bodyLen);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
public class NetData {
|
||||
private int routerId;
|
||||
private byte routerType;
|
||||
private int msgId;
|
||||
private int index;
|
||||
private byte[] content;
|
||||
|
||||
public int getRouterId() {
|
||||
return routerId;
|
||||
}
|
||||
|
||||
public void setRouterId(int routerId) {
|
||||
this.routerId = routerId;
|
||||
}
|
||||
|
||||
public byte getRouterType() {
|
||||
return routerType;
|
||||
}
|
||||
|
||||
public void setRouterType(byte routerType) {
|
||||
this.routerType = routerType;
|
||||
}
|
||||
|
||||
public int getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
public void setMsgId(int requestType) {
|
||||
this.msgId = requestType;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
public class PacketNetData {
|
||||
//
|
||||
private byte[] packetData;
|
||||
|
||||
public PacketNetData(byte[] packetData) {
|
||||
this.packetData = packetData;
|
||||
}
|
||||
|
||||
public void setPacketData(byte[] packetData) {
|
||||
this.packetData = packetData;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return Tea.byteToInt(packetData, 0);
|
||||
}
|
||||
|
||||
public int getToken() {
|
||||
return Tea.byteToInt(packetData, 4);
|
||||
}
|
||||
|
||||
public int getMsgId() {
|
||||
return Tea.byteToInt(packetData, 8);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return Tea.byteToInt(packetData, 12);
|
||||
}
|
||||
|
||||
public int getResult() {
|
||||
return Tea.byteToInt(packetData, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 只获取协议信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public byte[] parseClientProtoNetData() {
|
||||
byte[] data = new byte[packetData.length - 16];
|
||||
System.arraycopy(packetData, 16, data, 0, data.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public byte[] parseServerProtoNetData() {
|
||||
byte[] data = new byte[packetData.length - 20];
|
||||
System.arraycopy(packetData, 20, data, 0, data.length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全部数据
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public byte[] getPacketData() {
|
||||
return packetData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package com.ljsd.jieling.netty.cocdex; /** */
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Tea算法
|
||||
* 每次操作可以处理8个字节数据
|
||||
* KEY为16字节,应为包含4个int型数的int[],一个int为4个字节
|
||||
* 加密解密轮数应为8的倍数,推荐加密轮数为64轮
|
||||
*/
|
||||
public class Tea {
|
||||
public static int[] KEY = new int[]{//加密解密所用的KEY
|
||||
0x789f5645, 0xf68bd5a4,
|
||||
0x81963ffa, 0x458fac58
|
||||
};
|
||||
private static int TIMES = 32;
|
||||
|
||||
public static int[] generateSecretKey() {
|
||||
Random rand = new Random();
|
||||
int[] secretKey = new int[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
secretKey[i] = rand.nextInt();
|
||||
}
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
//若某字节被解释成负的则需将其转成无符号正数
|
||||
private static int transform(byte temp) {
|
||||
int tempInt = (int) temp;
|
||||
if (tempInt < 0) {
|
||||
tempInt += 256;
|
||||
}
|
||||
return tempInt;
|
||||
}
|
||||
|
||||
public static int byteToInt(byte[] content, int offset) {
|
||||
int result = transform(content[offset + 3]) | transform(content[offset + 2]) << 8 |
|
||||
transform(content[offset + 1]) << 16 | (int) content[offset] << 24;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void intToByte(byte[] bys, int offset, int content) {
|
||||
bys[offset + 3] = (byte) (content & 0xff);
|
||||
bys[offset + 2] = (byte) ((content >> 8) & 0xff);
|
||||
bys[offset + 1] = (byte) ((content >> 16) & 0xff);
|
||||
bys[offset] = (byte) ((content >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//byte[]型数据转成int[]型数据
|
||||
private static int[] byteToIntArray(byte[] content, int offset) {
|
||||
|
||||
int[] result = new int[content.length >> 2]; //除以2的n次方 == 右移n位 即 content.length / 4 == content.length >> 2
|
||||
for (int i = 0, j = offset; j < content.length; i++, j += 4) {
|
||||
result[i] = byteToInt(content, j);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//int[]型数据转成byte[]型数据
|
||||
private static byte[] intArrayToByte(int[] content, int offset) {
|
||||
byte[] result = new byte[content.length << 2]; //乘以2的n次方 == 左移n位 即 content.length * 4 == content.length << 2
|
||||
for (int i = 0, j = offset; j < result.length; i++, j += 4) {
|
||||
intToByte(result, j, content[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//加密
|
||||
public static byte[] encrypt(byte[] content, int offset, int[] key, int times) {//times为加密轮数
|
||||
int[] tempInt = byteToIntArray(content, offset);
|
||||
int y = tempInt[0], z = tempInt[1], sum = 0, i;
|
||||
int delta = 0x9e3779b9; //这是算法标准给的值
|
||||
int a = key[0], b = key[1], c = key[2], d = key[3];
|
||||
|
||||
for (i = 0; i < times; i++) {
|
||||
sum += delta;
|
||||
y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
|
||||
z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
|
||||
}
|
||||
tempInt[0] = y;
|
||||
tempInt[1] = z;
|
||||
return intArrayToByte(tempInt, 0);
|
||||
}
|
||||
|
||||
//解密
|
||||
public static byte[] decrypt(byte[] encryptContent, int offset, int[] key, int times) {
|
||||
int[] tempInt = byteToIntArray(encryptContent, offset);
|
||||
int y = tempInt[0], z = tempInt[1], sum = 0xC6EF3720, i;
|
||||
int delta = 0x9e3779b9; //这是算法标准给的值
|
||||
int a = key[0], b = key[1], c = key[2], d = key[3];
|
||||
|
||||
for (i = 0; i < times; i++) {
|
||||
z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
|
||||
y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
|
||||
sum -= delta;
|
||||
}
|
||||
tempInt[0] = y;
|
||||
tempInt[1] = z;
|
||||
|
||||
return intArrayToByte(tempInt, 0);
|
||||
}
|
||||
|
||||
public static void shortToByte(byte[] bys, int offset, int content) {
|
||||
bys[offset + 1] = (byte) (content & 0xff);
|
||||
bys[offset] = (byte) ((content >> 8) & 0xff);
|
||||
}
|
||||
|
||||
public static int byteToShort(byte[] content, int offset) {
|
||||
int result = transform(content[offset + 1]) | transform(content[offset]) << 8;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] encrypt2(byte[] content, int[] key) {
|
||||
byte[] bys = content;
|
||||
if (bys.length % 8 != 0) {
|
||||
bys = new byte[(bys.length + 7) / 8 * 8];
|
||||
System.arraycopy(content, 0, bys, 0, content.length);
|
||||
}
|
||||
byte[] encryptContent = encrypt(bys, 0, key, TIMES);
|
||||
byte[] result = new byte[encryptContent.length + 2];
|
||||
shortToByte(result, 0, content.length);
|
||||
System.arraycopy(encryptContent, 0, result, 2, encryptContent.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] decrypt2(byte[] encryptContent, int len, int offset, int[] key) {
|
||||
byte[] decryptContent = decrypt(encryptContent, offset, key, TIMES);
|
||||
if (len == decryptContent.length) {
|
||||
return decryptContent;
|
||||
}
|
||||
byte[] bys = new byte[len];
|
||||
System.arraycopy(decryptContent, 0, bys, 0, len);
|
||||
return bys;
|
||||
}
|
||||
|
||||
|
||||
// public static byte[] encrypt3(NetData netData, int[] key) {
|
||||
// //4:routerId, 1:routerType+reqestType
|
||||
// //取8的整数倍长度
|
||||
// int length = netData.getContent().length + 19;
|
||||
// byte[] plainText = new byte[length];
|
||||
//
|
||||
// intToByte(plainText, 0, netData.getRouterId());
|
||||
// plainText[4] = netData.getRouterType();
|
||||
// intToByte(plainText, 5, netData.getMsgId());
|
||||
// System.arraycopy(netData.getContent(), 0, plainText, 19, netData.getContent().length);
|
||||
// return encrypt2(plainText, key);
|
||||
// }
|
||||
//
|
||||
// public static PacketNetData decrypt3(int length, byte[] encryptContent, int offset, int[] key) {
|
||||
// byte[] decryptContent = decrypt2(encryptContent, length, offset, key);
|
||||
// PacketNetData packetNetData = new PacketNetData(decryptContent);
|
||||
// return packetNetData;
|
||||
// }
|
||||
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String plainStr = "123";
|
||||
// byte[] encryptBys = encrypt2(plainStr.getBytes(), KEY);
|
||||
// int length = byteToShort(encryptBys, 0);
|
||||
// byte[] decodeBys = decrypt2(encryptBys, length, 2, KEY);
|
||||
// String decryptStr = new String(decodeBys);
|
||||
// System.out.println("decryptStr=" + decryptStr);
|
||||
//
|
||||
// NetData netData = new NetData();
|
||||
// long startTime = System.currentTimeMillis();
|
||||
// netData.setContent(new byte[50]);
|
||||
// for (int i = 0; i < netData.getContent().length; i++) {
|
||||
// netData.getContent()[i] = (byte) i;
|
||||
// }
|
||||
// netData.setRouterId(1);
|
||||
// netData.setRouterType((byte) 2);
|
||||
// netData.setMsgId(3);
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
// byte[] secretInfo = encrypt3(netData, KEY);
|
||||
// length = byteToShort(secretInfo, 0);
|
||||
// PacketNetData packetNetData = decrypt3(length, secretInfo, 2, KEY);
|
||||
//
|
||||
// if (netData.getRouterId() != packetNetData.getRouterId()) {
|
||||
// System.out.println("netData.routerId != netData2.routerId");
|
||||
// return;
|
||||
// }
|
||||
// if (netData.getRouterType() != packetNetData.getRouterType()) {
|
||||
// System.out.println("netData.routerType != netData2.routerType");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// byte[] data = packetNetData.getMsgIdAndPBData();
|
||||
// if (netData.getContent().length != data.length) {
|
||||
// System.out.println("netData.content.length != netData2.content.length");
|
||||
// return;
|
||||
// }
|
||||
// int j;
|
||||
// for (j = 0; j < netData.getContent().length; j++) {
|
||||
// if (netData.getContent()[j] != data[j]) {
|
||||
// System.out.println("decryptInfo[j] != info[j]");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// long endTime = System.currentTimeMillis();
|
||||
// //加解密10万,用时91毫秒
|
||||
// System.out.println("加解密10万,用时" + (endTime - startTime) + "毫秒");
|
||||
// }
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TeaDecoder extends ByteToMessageDecoder {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TeaDecoder.class);
|
||||
|
||||
public TeaDecoder(){
|
||||
}
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
String secret_key = "";
|
||||
|
||||
try {
|
||||
in.markReaderIndex();
|
||||
final byte[] buf = new byte[2];
|
||||
for (int i = 0; i < buf.length; i ++) {
|
||||
if (!in.isReadable()) {
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}
|
||||
|
||||
buf[i] = in.readByte();
|
||||
}
|
||||
int length = Tea.byteToShort(buf, 0);
|
||||
int encodeLen = (length +7) / 8 * 8;
|
||||
if(length == 0){
|
||||
LOGGER.debug("decode->receive empty heartbeat parackage");
|
||||
return;
|
||||
}
|
||||
if (in.readableBytes() < encodeLen){
|
||||
in.resetReaderIndex();
|
||||
return;
|
||||
}else{
|
||||
ByteBuf message = in.readBytes(encodeLen);
|
||||
// int[] secretKey = SessionManager.getSecretKey(ctx);
|
||||
int[] secretKey = Tea.KEY;
|
||||
byte[] packetNetData = Tea.decrypt2( message.array(), length,0, secretKey);
|
||||
out.add(packetNetData);
|
||||
}
|
||||
}catch (Exception e){
|
||||
LOGGER.error("decode->secret_key={},emsg={}", secret_key, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.ljsd.jieling.netty.cocdex;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class TeaEncoder extends MessageToByteEncoder<byte[]> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TeaDecoder.class);
|
||||
|
||||
public TeaEncoder(){
|
||||
}
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) {
|
||||
try {
|
||||
int[] secretKey;
|
||||
// if (CtxUtil.isFirstPacket(ctx)) {
|
||||
// secretKey = Tea.KEY;
|
||||
// } else {
|
||||
// secretKey = SessionManager.getSecretKey(ctx);
|
||||
// }
|
||||
|
||||
// out.writeShort((short) msg.length);
|
||||
out.writeBytes(msg, 0, msg.length);
|
||||
|
||||
// System.out.println(out.array());
|
||||
} catch (Exception e){
|
||||
LOGGER.error("decode->emsg={}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.ljsd.jieling.netty.handler;
|
||||
|
||||
import com.ljsd.jieling.netty.NettyGameSession;
|
||||
import com.ljsd.jieling.protocol.ProtocolsAbstract;
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.group.ChannelGroup;
|
||||
import io.netty.channel.group.DefaultChannelGroup;
|
||||
import io.netty.handler.timeout.IdleState;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import io.netty.util.AttributeKey;
|
||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class GameMessageHandler<T extends GameSession> extends SimpleChannelInboundHandler<Object> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GameMessageHandler.class);
|
||||
|
||||
public static Map<Integer, NettyGameSession> currentSessions = new ConcurrentHashMap<>();
|
||||
public static ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
|
||||
|
||||
static final AttributeKey<GameSession> DEBUG_SESSION_KEY = AttributeKey.valueOf("DEBUG_SESSION_KEY");
|
||||
private final T session;
|
||||
private final ProtocolsAbstract protocols;
|
||||
|
||||
public GameMessageHandler(T session, ProtocolsAbstract protocols) {
|
||||
this.session = session;
|
||||
this.protocols = protocols;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
LOGGER.info("seission"+this.session+"channelActive: " + ctx.channel().remoteAddress()+" ,uid: "+
|
||||
((NettyGameSession) this.session).getUid() +" ,areaId: "+ ((NettyGameSession) this.session).getAreaId());
|
||||
ctx.channel().attr(DEBUG_SESSION_KEY).set(this.session);
|
||||
((NettyGameSession) this.session).setCtx(ctx);
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
LOGGER.info("channelInactive->uid={},seission={},remoteAddress={}",
|
||||
((NettyGameSession) this.session).getUid(), this.session, ctx.channel().remoteAddress());
|
||||
protocols.offLine(this.session);
|
||||
((NettyGameSession) this.session).setCtx(null);
|
||||
ctx.channel().attr(DEBUG_SESSION_KEY).remove();
|
||||
ctx.flush();
|
||||
ctx.close();
|
||||
super.channelInactive(ctx);
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
LOGGER.info("111111111111");
|
||||
protocols.processMessage(this.session, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
super.userEventTriggered(ctx, evt);
|
||||
if (evt instanceof IdleStateEvent) {
|
||||
IdleStateEvent e = (IdleStateEvent) evt;
|
||||
if (e.state() == IdleState.READER_IDLE) {
|
||||
protocols.readIdel(this.session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
//ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
// cause.printStackTrace();
|
||||
// LOGGER.debug("client have disconnected:-->"+cause.getMessage()+" IP:"+ctx.channel().remoteAddress());
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package com.ljsd.jieling.netty.handler;
|
||||
|
||||
import com.google.protobuf.MessageLite;
|
||||
import com.ljsd.jieling.protocol.ProtocolsAbstract;
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ServerResponseMessageHandler<T extends GameSession> extends SimpleChannelInboundHandler<MessageLite> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ServerResponseMessageHandler.class);
|
||||
private volatile Channel channel;
|
||||
|
||||
private final T session;
|
||||
private final ProtocolsAbstract protocols;
|
||||
|
||||
public ServerResponseMessageHandler(T session, ProtocolsAbstract protocols) {
|
||||
this.session = session;
|
||||
this.protocols = protocols;
|
||||
}
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRegistered(ChannelHandlerContext ctx) {
|
||||
channel = ctx.channel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
LOGGER.info("userEventTriggered->evt=" + evt);
|
||||
if (evt instanceof IdleStateEvent) {
|
||||
// 不管是读事件空闲还是写事件空闲都向服务器发送心跳包
|
||||
protocols.readIdel(this.session);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
LOGGER.info("exceptionCaught->remoteAddress={}" +
|
||||
ctx.channel().remoteAddress().toString());
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
LOGGER.info("channelInactive->run");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
|
||||
LOGGER.info("channelReadComplete->run");
|
||||
super.channelReadComplete(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, MessageLite msg) throws Exception {
|
||||
LOGGER.info("channelRead0->run");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package com.ljsd.jieling.netty.server;
|
||||
|
||||
import com.google.protobuf.MessageLite;
|
||||
import com.ljsd.jieling.netty.cocdex.Int32FrameDecoder;
|
||||
import com.ljsd.jieling.netty.cocdex.Int32LengthFieldPrepender;
|
||||
import com.ljsd.jieling.netty.handler.ServerResponseMessageHandler;
|
||||
import com.ljsd.jieling.protocol.ProtocolsAbstract;
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
import com.ljsd.jieling.session.GameSessionFactory;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||
import io.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NettyGameClient<T extends GameSession> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NettyGameClient.class);
|
||||
private static Bootstrap bootstrap = null;
|
||||
//key位IP+Port的组合
|
||||
private static Map<String, Channel> channels = new ConcurrentHashMap<>();
|
||||
|
||||
private final int readTimeout;
|
||||
private final int writeTimeout;
|
||||
private final int allTimeout;
|
||||
private final MessageLite gameMessage;
|
||||
private final ProtocolsAbstract protocols;
|
||||
private final GameSessionFactory<T> sessionFactory;
|
||||
|
||||
|
||||
public NettyGameClient(int readTimeout, int writeTimeout,
|
||||
int allTimeout, MessageLite gameMessage, ProtocolsAbstract protocols, GameSessionFactory<T> sessionFactory) {
|
||||
this.readTimeout = readTimeout;
|
||||
this.writeTimeout = writeTimeout;
|
||||
this.allTimeout = allTimeout;
|
||||
this.gameMessage = gameMessage;
|
||||
this.protocols = protocols;
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
try {
|
||||
EventLoopGroup group = new NioEventLoopGroup(1);
|
||||
bootstrap = new Bootstrap();
|
||||
bootstrap.group(group)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
|
||||
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||
.option(ChannelOption.SO_LINGER, 0)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
|
||||
p.addLast(new Int32FrameDecoder());
|
||||
p.addLast(new ProtobufDecoder(gameMessage));
|
||||
|
||||
// 心跳检测处理
|
||||
p.addLast(new IdleStateHandler(readTimeout, writeTimeout, allTimeout, TimeUnit.SECONDS));
|
||||
|
||||
p.addLast(new Int32LengthFieldPrepender());
|
||||
p.addLast(new ProtobufEncoder());
|
||||
|
||||
p.addLast(new ServerResponseMessageHandler(sessionFactory.createGameSession(), protocols));
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("start->msg={}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
public static Channel getChannel(String serverIp, int port) {
|
||||
try {
|
||||
String key = serverIp + ":" + port;
|
||||
Channel channel = channels.get(key);
|
||||
if(channel == null || !channel.isOpen() || !channel.isActive()) {
|
||||
channel = bootstrap.connect(serverIp, port).sync().channel();
|
||||
channels.put(key, channel);
|
||||
}
|
||||
return channel;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("getChannel->serverIp={},port={},msg={}", serverIp, port, e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Channel getChannel(String serverIpPort) {
|
||||
String strs[] = serverIpPort.split(":");
|
||||
return getChannel(strs[0], Integer.parseInt(strs[1]));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.ljsd.jieling.netty.server;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.ljsd.jieling.netty.cocdex.TeaDecoder;
|
||||
import com.ljsd.jieling.netty.cocdex.TeaEncoder;
|
||||
import com.ljsd.jieling.netty.handler.GameMessageHandler;
|
||||
import com.ljsd.jieling.protocol.ProtocolsAbstract;
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
import com.ljsd.jieling.session.GameSessionFactory;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class NettyGameServer<T extends GameSession> {
|
||||
|
||||
private final int tcpPort;
|
||||
private final int readTimeout;
|
||||
private final int writeTimeout;
|
||||
private final int allTimeout;
|
||||
// private final MessageLite gameMessage;
|
||||
private final ProtocolsAbstract protocols;
|
||||
private final GameSessionFactory<T> sessionFactory;
|
||||
private EventLoopGroup bossGroup;
|
||||
private EventLoopGroup workerGroup;
|
||||
|
||||
public NettyGameServer(int tcpPort, int readTimeout, int writeTimeout,
|
||||
int allTimeout, ProtocolsAbstract protocols, GameSessionFactory<T> sessionFactory) {
|
||||
this.tcpPort = tcpPort;
|
||||
this.readTimeout = readTimeout;
|
||||
this.writeTimeout = writeTimeout;
|
||||
this.allTimeout = allTimeout;
|
||||
// this.gameMessage = gameMessage;
|
||||
this.protocols = protocols;
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
// @SuppressWarnings("unused")
|
||||
// private ChannelFuture channelFuture = null;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void start() throws Exception {
|
||||
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("netty-%d").build();
|
||||
|
||||
bossGroup = new NioEventLoopGroup(0, factory);
|
||||
workerGroup = new NioEventLoopGroup(16, factory);
|
||||
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
||||
serverBootstrap.group(bossGroup, workerGroup).option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
|
||||
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).channel(NioServerSocketChannel.class)
|
||||
.option(ChannelOption.SO_LINGER, 0)
|
||||
.handler(new LoggingHandler(LogLevel.DEBUG))
|
||||
.childHandler(new ChannelInitializer() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initChannel(Channel ch) throws Exception {
|
||||
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
|
||||
// 心跳检测处理
|
||||
p.addLast(new IdleStateHandler(readTimeout, writeTimeout, allTimeout, TimeUnit.SECONDS));
|
||||
|
||||
p.addLast(new TeaDecoder());
|
||||
p.addLast(new TeaEncoder());
|
||||
|
||||
p.addLast(new GameMessageHandler(NettyGameServer.this.sessionFactory.createGameSession(), protocols));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
|
||||
serverBootstrap.bind(tcpPort).sync().channel().closeFuture().sync();
|
||||
|
||||
} finally {
|
||||
bossGroup.shutdownGracefully().sync();
|
||||
workerGroup.shutdownGracefully().sync();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws Exception {
|
||||
bossGroup.shutdownGracefully().sync();
|
||||
workerGroup.shutdownGracefully().sync();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.ljsd.jieling.protocol;
|
||||
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.ljsd.jieling.session.GameSession;
|
||||
|
||||
public interface ProtocolsAbstract {
|
||||
|
||||
void processMessage(GameSession gameSession, final Object gameMessage) throws InvalidProtocolBufferException;
|
||||
|
||||
void offLine(GameSession gameSession);
|
||||
|
||||
void readIdel(GameSession gameSession);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.ljsd.jieling.session;
|
||||
|
||||
public interface GameSession {
|
||||
|
||||
boolean isOnline();
|
||||
|
||||
void write(Object paramObject);
|
||||
|
||||
void close();
|
||||
|
||||
void postClose();
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.ljsd.jieling.session;
|
||||
|
||||
public interface GameSessionFactory<T extends GameSession> {
|
||||
|
||||
T createGameSession();
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue