新增安卓端模版,目前只具备启动界面和基础通讯功能,有待完善,v1.7.4
9
AndroidTemplate/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
19
AndroidTemplate/.idea/gradle.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="LOCAL" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-4.3" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
33
AndroidTemplate/.idea/misc.xml
generated
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
9
AndroidTemplate/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/AndroidTemplate.iml" filepath="$PROJECT_DIR$/AndroidTemplate.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
12
AndroidTemplate/.idea/runConfigurations.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
1
AndroidTemplate/app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
31
AndroidTemplate/app/build.gradle
Normal file
@@ -0,0 +1,31 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
defaultConfig {
|
||||
applicationId "com.example.UserSoftwareAndroidTemplate"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
buildToolsVersion '27.0.0'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
implementation 'com.android.support:design:26.1.0'
|
||||
implementation 'com.android.support:support-v4:26.1.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||
}
|
||||
21
AndroidTemplate/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.UserSoftwareAndroidTemplate;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.example.UserSoftwareAndroidTemplate", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
31
AndroidTemplate/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.UserSoftwareAndroidTemplate">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".LoginSupport.SplashActivity"
|
||||
android:configChanges="keyboardHidden"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.HslCommunication.BasicFramework;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
* 静态类,提供许多程序运行的方法
|
||||
*/
|
||||
|
||||
public class SoftBasic {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package com.example.HslCommunication.BasicFramework;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
*/
|
||||
|
||||
public class SystemVersion {
|
||||
|
||||
/// <summary>
|
||||
/// 根据格式化字符串的版本号初始化
|
||||
/// </summary>
|
||||
/// <param name="VersionString">格式化的字符串,例如:1.0.0或1.0.0.0503</param>
|
||||
public SystemVersion(String VersionString)
|
||||
{
|
||||
String[] temp = VersionString.split("\\.");
|
||||
if (temp.length >= 3)
|
||||
{
|
||||
m_MainVersion = Integer.parseInt(temp[0]);
|
||||
m_SecondaryVersion = Integer.parseInt(temp[1]);
|
||||
m_EditVersion = Integer.parseInt(temp[2]);
|
||||
|
||||
if (temp.length >= 4)
|
||||
{
|
||||
m_InnerVersion = Integer.parseInt(temp[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据指定的数字实例化一个对象
|
||||
/// </summary>
|
||||
/// <param name="main">主版本</param>
|
||||
/// <param name="sec">次版本</param>
|
||||
/// <param name="edit">修订版</param>
|
||||
public SystemVersion(int main, int sec, int edit)
|
||||
{
|
||||
m_MainVersion = main;
|
||||
m_SecondaryVersion = sec;
|
||||
m_EditVersion = edit;
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据指定的数字实例化一个对象
|
||||
/// </summary>
|
||||
/// <param name="main">主版本</param>
|
||||
/// <param name="sec">次版本</param>
|
||||
/// <param name="edit">修订版</param>
|
||||
/// <param name="inner">内部版本号</param>
|
||||
public SystemVersion(int main, int sec, int edit, int inner)
|
||||
{
|
||||
m_MainVersion = main;
|
||||
m_SecondaryVersion = sec;
|
||||
m_EditVersion = edit;
|
||||
m_InnerVersion = inner;
|
||||
}
|
||||
private int m_MainVersion = 2;
|
||||
/// <summary>
|
||||
/// 主版本
|
||||
/// </summary>
|
||||
public int MainVersion()
|
||||
{
|
||||
return m_MainVersion;
|
||||
}
|
||||
private int m_SecondaryVersion = 0;
|
||||
/// <summary>
|
||||
/// 次版本
|
||||
/// </summary>
|
||||
public int SecondaryVersion() {
|
||||
return m_SecondaryVersion;
|
||||
}
|
||||
|
||||
private int m_EditVersion = 0;
|
||||
/// <summary>
|
||||
/// 修订版
|
||||
/// </summary>
|
||||
public int EditVersion() {
|
||||
return m_EditVersion;
|
||||
}
|
||||
private int m_InnerVersion = 0;
|
||||
/// <summary>
|
||||
/// 内部版本号,或者是版本号表示为年月份+内部版本的表示方式
|
||||
/// </summary>
|
||||
public int InnerVersion()
|
||||
{
|
||||
return m_InnerVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据格式化为支持返回的不同信息的版本号
|
||||
/// C返回1.0.0.0
|
||||
/// N返回1.0.0
|
||||
/// S返回1.0
|
||||
/// </summary>
|
||||
/// <param name="format">格式化信息</param>
|
||||
/// <returns></returns>
|
||||
public String toString(String format)
|
||||
{
|
||||
if(format == "C")
|
||||
{
|
||||
return MainVersion()+"."+SecondaryVersion()+"."+EditVersion()+"."+InnerVersion();
|
||||
}
|
||||
|
||||
if(format == "N")
|
||||
{
|
||||
return MainVersion()+"."+SecondaryVersion()+"."+EditVersion();
|
||||
}
|
||||
|
||||
if(format == "S")
|
||||
{
|
||||
return MainVersion()+"."+SecondaryVersion();
|
||||
}
|
||||
|
||||
return toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if(InnerVersion() == 0)
|
||||
{
|
||||
return MainVersion()+"."+SecondaryVersion()+"."+EditVersion();
|
||||
}
|
||||
else
|
||||
{
|
||||
return MainVersion()+"."+SecondaryVersion()+"."+EditVersion()+"."+InnerVersion();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean IsSameVersion(SystemVersion sv)
|
||||
{
|
||||
if(this.m_MainVersion!=sv.m_MainVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.m_SecondaryVersion!=sv.m_SecondaryVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.m_EditVersion!=sv.m_EditVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.m_InnerVersion!=sv.m_InnerVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class HslCommunicationCode {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 规定所有的网络传输指令头都为32字节
|
||||
/// </summary>
|
||||
public static final int HeadByteLength = 32;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 用于心跳程序的暗号信息
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_Check_Secends = 1;
|
||||
/// <summary>
|
||||
/// 客户端退出消息
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_Client_Quit = 2;
|
||||
/// <summary>
|
||||
/// 因为客户端达到上限而拒绝登录
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_Client_Refuse_Login = 3;
|
||||
/// <summary>
|
||||
/// 允许客户端登录到服务器
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_Client_Allow_Login = 4;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 说明发送的只是文本信息
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_User_String = 1001;
|
||||
/// <summary>
|
||||
/// 发送的数据就是普通的字节数组
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_User_Bytes = 1002;
|
||||
/// <summary>
|
||||
/// 发送的数据就是普通的图片数据
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_User_Bitmap = 1003;
|
||||
/// <summary>
|
||||
/// 发送的数据是一条异常的数据,字符串为异常消息
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_User_Exception = 1004;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 请求文件下载的暗号
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Download = 2001;
|
||||
/// <summary>
|
||||
/// 请求文件上传的暗号
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Upload = 2002;
|
||||
/// <summary>
|
||||
/// 请求删除文件的暗号
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Delete = 2003;
|
||||
/// <summary>
|
||||
/// 文件校验成功
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Check_Right = 2004;
|
||||
/// <summary>
|
||||
/// 文件校验失败
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Check_Error = 2005;
|
||||
/// <summary>
|
||||
/// 文件保存失败
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Save_Error = 2006;
|
||||
/// <summary>
|
||||
/// 请求文件列表的暗号
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Directory_Files = 2007;
|
||||
/// <summary>
|
||||
/// 请求子文件的列表暗号
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_File_Directories = 2008;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 不压缩数据字节
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_NoZipped = 3001;
|
||||
/// <summary>
|
||||
/// 压缩数据字节
|
||||
/// </summary>
|
||||
public static final int Hsl_Protocol_Zipped = 3002;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class HslSecurity {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 加密方法,只对当前的程序集开放
|
||||
/// </summary>
|
||||
/// <param name="enBytes">等待加密的数据</param>
|
||||
/// <returns>加密后的数据</returns>
|
||||
public static byte[] ByteEncrypt(byte[] enBytes) {
|
||||
if (enBytes == null) return null;
|
||||
byte[] result = new byte[enBytes.length];
|
||||
for (int i = 0; i < enBytes.length; i++) {
|
||||
result[i] = (byte) (enBytes[i] ^ 0xB5);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 解密方法,只对当前的程序集开放
|
||||
/// </summary>
|
||||
/// <param name="deBytes">等待解密的数据</param>
|
||||
/// <returns>解密后的数据</returns>
|
||||
public static byte[] ByteDecrypt(byte[] deBytes) {
|
||||
return ByteEncrypt(deBytes);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class HslZipped {
|
||||
|
||||
|
||||
/***
|
||||
* 压缩GZip
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static byte[] CompressBytes(byte[] data) {
|
||||
byte[] b = null;
|
||||
try {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(bos);
|
||||
gzip.write(data);
|
||||
gzip.finish();
|
||||
gzip.close();
|
||||
b = bos.toByteArray();
|
||||
bos.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/***
|
||||
* 解压GZip
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
public static byte[] Decompress(byte[] data) {
|
||||
byte[] b = null;
|
||||
try {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
GZIPInputStream gzip = new GZIPInputStream(bis);
|
||||
byte[] buf = new byte[1024];
|
||||
int num = -1;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
while ((num = gzip.read(buf, 0, buf.length)) != -1) {
|
||||
baos.write(buf, 0, num);
|
||||
}
|
||||
b = baos.toByteArray();
|
||||
baos.flush();
|
||||
baos.close();
|
||||
gzip.close();
|
||||
bis.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
import android.util.Log;
|
||||
|
||||
import com.example.HslCommunication.Core.Types.HslTimeOut;
|
||||
import com.example.HslCommunication.Core.Types.OperateResult;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithBytes;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithSocket;
|
||||
import com.example.HslCommunication.Log.LogUtil;
|
||||
import com.example.HslCommunication.Resources.StringResources;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
* 该类提供基础的网络操作服务,读写字节流,读写文件流
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public abstract class NetBase {
|
||||
|
||||
/// <summary>
|
||||
/// 用于通信工作的核心对象
|
||||
/// </summary>
|
||||
protected Socket WorkSocket = null;
|
||||
/// <summary>
|
||||
/// 分次接收的数据长度
|
||||
/// </summary>
|
||||
public int SegmentationLength = 1024;
|
||||
|
||||
/// <summary>
|
||||
/// 检查超时的子线程
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public void ThreadPoolCheckConnect(Object obj) {
|
||||
HslTimeOut timeout = (HslTimeOut) obj;
|
||||
if (timeout != null) {
|
||||
NetSupport.ThreadPoolCheckConnect(timeout, ConnectTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 网络访问中的超时时间,单位:毫秒,默认值5000
|
||||
/// </summary>
|
||||
public int ConnectTimeout = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// 当前对象的身份令牌,用来在网络通信中双向认证的依据
|
||||
/// </summary>
|
||||
public UUID KeyToken = UUID.randomUUID();
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* 1. 创建并连接套接字
|
||||
* 2. 接收指定长度的字节数据
|
||||
* 3. 发送字节数据到套接字
|
||||
* 4. 检查对方是否接收完成
|
||||
* 5. 检查头子节令牌是否通过
|
||||
* 6. 将文件流写入套接字
|
||||
* 7. 从套接字接收文件流
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建socket对象并尝试连接终结点,如果异常,则结束通信
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="iPEndPoint">网络终结点</param>
|
||||
/// <param name="result">结果对象</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
protected boolWithSocket CreateSocketAndConnect(
|
||||
String ipAddress,
|
||||
int port,
|
||||
OperateResult result
|
||||
) {
|
||||
boolWithSocket value = new boolWithSocket();
|
||||
try {
|
||||
// create the socket object
|
||||
value.Socket = new Socket(ipAddress, port);
|
||||
value.Result = true;
|
||||
return value;
|
||||
} catch (Exception ex) {
|
||||
result.Message = StringResources.ConnectedFailed;
|
||||
LogUtil.LogE("CreateSocketAndConnect", StringResources.ConnectedFailed, ex);
|
||||
CloseSocket(value.Socket);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 仅仅接收一定长度的字节数据,如果异常,则结束通信
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="bytes">字节数据</param>
|
||||
/// <param name="length">长度</param>
|
||||
/// <param name="result">结果对象</param>
|
||||
/// <param name="receiveStatus">接收状态</param>
|
||||
/// <param name="reportByPercent">是否根据百分比报告进度</param>
|
||||
/// <param name="response">是否回发进度</param>
|
||||
/// <param name="checkTimeOut">是否进行超时检查</param>
|
||||
/// <param name="exceptionMessage">假设发生异常,应该携带什么信息</param>
|
||||
/// <returns></returns>
|
||||
protected boolWithBytes ReceiveBytesFromSocket(
|
||||
Socket socket,
|
||||
int length,
|
||||
OperateResult result,
|
||||
ProgressReport receiveStatus,
|
||||
boolean reportByPercent,
|
||||
boolean response,
|
||||
boolean checkTimeOut,
|
||||
String exceptionMessage
|
||||
) {
|
||||
boolWithBytes value = new boolWithBytes();
|
||||
|
||||
try {
|
||||
value.Content = NetSupport.ReadBytesFromSocket(socket, length, receiveStatus, reportByPercent, response);
|
||||
} catch (Exception ex) {
|
||||
CloseSocket(socket);
|
||||
result.Message = CombineExceptionString(exceptionMessage, ex.getMessage());
|
||||
LogUtil.LogE("ReceiveBytesFromSocket", exceptionMessage, ex);
|
||||
Log.e("接收数据异常", "ReceiveBytesFromSocket: ", ex);
|
||||
return value;
|
||||
}
|
||||
value.Result = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅仅将数据发送到socket对象上去,如果异常,则结束通信
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="send"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="exceptionMessage"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendBytesToSocket(
|
||||
Socket socket,
|
||||
byte[] send,
|
||||
OperateResult result,
|
||||
String exceptionMessage
|
||||
) {
|
||||
try {
|
||||
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
|
||||
output.write(send);
|
||||
} catch (Exception ex) {
|
||||
result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
|
||||
LogUtil.LogE("SendBytesToSocket", exceptionMessage, ex);
|
||||
CloseSocket(socket);
|
||||
send = null;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 确认对方是否已经接收完成数据,如果异常,则结束通信
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="report"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="exceptionMessage"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean CheckRomoteReceived(
|
||||
Socket socket,
|
||||
long length,
|
||||
ProgressReport report,
|
||||
OperateResult result,
|
||||
String exceptionMessage
|
||||
) {
|
||||
try {
|
||||
NetSupport.CheckSendBytesReceived(socket, length, report, true);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
|
||||
LogUtil.LogE("CheckRomoteReceived", exceptionMessage, ex);
|
||||
CloseSocket(socket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查令牌是否正确,如果不正确,结束网络通信
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="head">头子令</param>
|
||||
/// <param name="token">令牌</param>
|
||||
/// <param name="result">结果对象</param>
|
||||
/// <returns></returns>
|
||||
protected boolean CheckTokenPermission(
|
||||
Socket socket,
|
||||
byte[] head,
|
||||
UUID token,
|
||||
OperateResult result
|
||||
) {
|
||||
if (NetSupport.CheckTokenEquel(head, KeyToken)) {
|
||||
return true;
|
||||
} else {
|
||||
result.Message = StringResources.TokenCheckFailed;
|
||||
LogUtil.LogE("CheckTokenPermission", StringResources.TokenCheckFailed + " Ip:" + socket.getInetAddress().toString());
|
||||
CloseSocket(socket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将文件数据发送至套接字,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="filelength"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="report"></param>
|
||||
/// <param name="exceptionMessage"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendFileStreamToSocket(
|
||||
Socket socket,
|
||||
String filename,
|
||||
long filelength,
|
||||
OperateResult result,
|
||||
ProgressReport report,
|
||||
String exceptionMessage
|
||||
) {
|
||||
try {
|
||||
InputStream inputStream = new BufferedInputStream(new FileInputStream(filename));
|
||||
NetSupport.WriteSocketFromStream(socket, inputStream, filelength, report, true);
|
||||
inputStream.close();
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
CloseSocket(socket);
|
||||
LogUtil.LogE("SendFileStreamToSocket", exceptionMessage, ex);
|
||||
result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从套接字中接收一个文件数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="receive"></param>
|
||||
/// <param name="report"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="exceptionMessage"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean ReceiveFileSteamFromSocket(
|
||||
Socket socket,
|
||||
String filename,
|
||||
long receive,
|
||||
ProgressReport report,
|
||||
OperateResult result,
|
||||
String exceptionMessage
|
||||
) {
|
||||
try {
|
||||
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filename));
|
||||
NetSupport.WriteStreamFromSocket(socket, outputStream, receive, report, true);
|
||||
outputStream.close();
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
result.Message = CombineExceptionString(exceptionMessage, ex.getLocalizedMessage());
|
||||
LogUtil.LogE("ReceiveFileSteamFromSocket", exceptionMessage, ex);
|
||||
CloseSocket(socket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取错误的用于显示的信息
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="exception"></param>
|
||||
/// <returns></returns>
|
||||
protected String CombineExceptionString(String message, String exception) {
|
||||
return message + "\r\n原因:" + exception;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void CloseSocket(Socket socket) {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (Exception ex2) {
|
||||
LogUtil.LogE("CloseSocket","",ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void ThreadSleep(int milltime)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(milltime);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,681 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.example.HslCommunication.Core.Types.OperateResult;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithBytes;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithIntByte;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithIntString;
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
import com.example.HslCommunication.Log.LogUtil;
|
||||
import com.example.HslCommunication.Resources.StringResources;
|
||||
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public abstract class NetShareBase extends NetBase {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="headcode">头指令</param>
|
||||
/// <param name="customer">用户指令</param>
|
||||
/// <param name="send">发送的数据</param>
|
||||
/// <param name="result">用于返回的结果</param>
|
||||
/// <param name="sendReport">发送的进度报告</param>
|
||||
/// <param name="failedString">失败时存储的额外描述信息</param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendBaseAndCheckReceive(
|
||||
Socket socket,
|
||||
int headcode,
|
||||
int customer,
|
||||
byte[] send,
|
||||
OperateResult result,
|
||||
ProgressReport sendReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
// 数据处理
|
||||
send = NetSupport.CommandBytes(headcode, customer, KeyToken, send);
|
||||
|
||||
Log.i(Utilities.bytes2HexString(send), "SendBaseAndCheckReceive: ");
|
||||
|
||||
// 发送数据
|
||||
if (!SendBytesToSocket(
|
||||
socket, // 套接字
|
||||
send, // 发送的字节数据
|
||||
result, // 结果信息对象
|
||||
failedString // 异常附加对象
|
||||
))
|
||||
{
|
||||
send = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确认对方是否接收完成
|
||||
int remoteReceive = send.length - HslCommunicationCode.HeadByteLength;
|
||||
Log.i("等待接收数据", "SendBaseAndCheckReceive: ");
|
||||
|
||||
if (!CheckRomoteReceived(
|
||||
socket, // 套接字
|
||||
remoteReceive, // 对方需要接收的长度
|
||||
sendReport, // 发送进度报告
|
||||
result, // 结果信息对象
|
||||
failedString // 异常附加信息
|
||||
))
|
||||
{
|
||||
send = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.i("对方接收成功", "SendBaseAndCheckReceive: ");
|
||||
// 对方接收成功
|
||||
send = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 发送字节数据并确认对方接收完成数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="customer">用户指令</param>
|
||||
/// <param name="send">发送的数据</param>
|
||||
/// <param name="result">用于返回的结果</param>
|
||||
/// <param name="sendReport">发送的进度报告</param>
|
||||
/// <param name="failedString">异常时记录到日志的附加信息</param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendBytesAndCheckReceive(
|
||||
Socket socket,
|
||||
int customer,
|
||||
byte[] send,
|
||||
OperateResult result,
|
||||
ProgressReport sendReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
if (SendBaseAndCheckReceive(
|
||||
socket, // 套接字
|
||||
HslCommunicationCode.Hsl_Protocol_User_Bytes, // 指示字节数组
|
||||
customer, // 用户数据
|
||||
send, // 发送数据,该数据还要经过处理
|
||||
result, // 结果消息对象
|
||||
sendReport, // 发送的进度报告
|
||||
failedString // 错误的额外描述
|
||||
))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogUtil.LogE("SendBytesAndCheckReceive",failedString);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 直接发送字符串数据并确认对方接收完成数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="customer">用户指令</param>
|
||||
/// <param name="send">发送的数据</param>
|
||||
/// <param name="result">用于返回的结果</param>
|
||||
/// <param name="sendReport">发送的进度报告</param>
|
||||
/// <param name="failedString"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendStringAndCheckReceive(
|
||||
Socket socket,
|
||||
int customer,
|
||||
String send,
|
||||
OperateResult result,
|
||||
ProgressReport sendReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
byte[] data =null;
|
||||
|
||||
if(send == null ||send.length() <= 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
data = send.getBytes();
|
||||
}
|
||||
|
||||
if (!SendBaseAndCheckReceive(
|
||||
socket, // 套接字
|
||||
HslCommunicationCode.Hsl_Protocol_User_String, // 指示字符串数据
|
||||
customer, // 用户数据
|
||||
data, // 字符串的数据
|
||||
result, // 结果消息对象
|
||||
sendReport, // 发送的进度报告
|
||||
failedString // 错误的额外描述
|
||||
))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// [自校验] 将文件数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="filename">文件名称,文件必须存在</param>
|
||||
/// <param name="servername">远程端的文件名称</param>
|
||||
/// <param name="filetag">文件的额外标签</param>
|
||||
/// <param name="fileupload">文件的上传人</param>
|
||||
/// <param name="result">操作结果对象</param>
|
||||
/// <param name="sendReport">发送进度报告</param>
|
||||
/// <param name="failedString"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendFileAndCheckReceive(
|
||||
Socket socket,
|
||||
String filename,
|
||||
String servername,
|
||||
String filetag,
|
||||
String fileupload,
|
||||
OperateResult result,
|
||||
ProgressReport sendReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
// 发送文件名,大小,标签
|
||||
File info = new File(filename);
|
||||
|
||||
//FileInfo info = new FileInfo(filename);
|
||||
|
||||
if (!info.exists())
|
||||
{
|
||||
// 如果文件不存在
|
||||
if (!SendStringAndCheckReceive(socket, 0, "", result, null, failedString)) return false;
|
||||
else
|
||||
{
|
||||
result.Message = "找不到该文件,请重新确认文件!";
|
||||
CloseSocket(socket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 文件存在的情况
|
||||
Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject
|
||||
{
|
||||
{ "FileName", new Newtonsoft.Json.Linq.JValue(servername) },
|
||||
{ "FileSize", new Newtonsoft.Json.Linq.JValue(info.Length) },
|
||||
{ "FileTag", new Newtonsoft.Json.Linq.JValue(filetag) },
|
||||
{ "FileUpload", new Newtonsoft.Json.Linq.JValue(fileupload) }
|
||||
};
|
||||
|
||||
if (!SendStringAndCheckReceive(socket, 1, json.ToString(), result, null, failedString)) return false;
|
||||
|
||||
|
||||
if (!SendFileStreamToSocket(socket, filename, info.Length, result, sendReport, failedString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查接收
|
||||
// if (!CheckRomoteReceived(socket, info.Length, sendReport, result, failedString))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 将流数据发送至套接字,具体发送细节将在继承类中实现,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="stream">文件名称,文件必须存在</param>
|
||||
/// <param name="servername">远程端的文件名称</param>
|
||||
/// <param name="filetag">文件的额外标签</param>
|
||||
/// <param name="fileupload">文件的上传人</param>
|
||||
/// <param name="result">操作结果对象</param>
|
||||
/// <param name="sendReport">发送进度报告</param>
|
||||
/// <param name="failedString"></param>
|
||||
/// <returns></returns>
|
||||
protected boolean SendFileAndCheckReceive(
|
||||
Socket socket,
|
||||
Stream stream,
|
||||
String servername,
|
||||
String filetag,
|
||||
String fileupload,
|
||||
OperateResult result,
|
||||
ProgressReport sendReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
// 文件存在的情况
|
||||
Newtonsoft.Json.Linq.JObject json = new Newtonsoft.Json.Linq.JObject
|
||||
{
|
||||
{ "FileName", new Newtonsoft.Json.Linq.JValue(servername) },
|
||||
{ "FileSize", new Newtonsoft.Json.Linq.JValue(stream.Length) },
|
||||
{ "FileTag", new Newtonsoft.Json.Linq.JValue(filetag) },
|
||||
{ "FileUpload", new Newtonsoft.Json.Linq.JValue(fileupload) }
|
||||
};
|
||||
|
||||
if (!SendStringAndCheckReceive(socket, 1, json.ToString(), result, null, failedString)) return false;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
NetSupport.WriteSocketFromStream(socket, stream, stream.Length, sendReport, true);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
if(LogNet!=null) LogNet.WriteException(failedString, ex);
|
||||
result.Message = CombineExceptionString(failedString, ex.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查接收
|
||||
// if (!CheckRomoteReceived(socket, info.Length, sendReport, result, failedString))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 接收一条完整的同步数据,包含头子节和内容字节,基础的数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="head">头子节</param>
|
||||
/// <param name="content">内容字节</param>
|
||||
/// <param name="result">结果</param>
|
||||
/// <param name="receiveReport">接收进度反馈</param>
|
||||
/// <param name="failedString">失败时用于显示的字符串</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException">result</exception>
|
||||
protected boolWith2Bytes ReceiveAndCheckBytes(
|
||||
Socket socket,
|
||||
OperateResult result,
|
||||
ProgressReport receiveReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
boolWith2Bytes value2=new boolWith2Bytes();
|
||||
|
||||
// 30秒超时接收验证
|
||||
// HslTimeOut hslTimeOut = new HslTimeOut()
|
||||
// {
|
||||
// DelayTime = 30000,
|
||||
// IsSuccessful = false,
|
||||
// StartTime = DateTime.Now,
|
||||
// WorkSocket = socket,
|
||||
// };
|
||||
//
|
||||
// ThreadPool.QueueUserWorkItem(new WaitCallback(NetSupport.ThreadPoolCheckTimeOut), hslTimeOut);
|
||||
|
||||
Log.i("准备接收头指令", "ReceiveAndCheckBytes: ");
|
||||
|
||||
boolWithBytes value = ReceiveBytesFromSocket(
|
||||
socket, // 套接字
|
||||
HslCommunicationCode.HeadByteLength, // 头指令长度
|
||||
result, // 结果消息对象
|
||||
null, // 不报告进度
|
||||
false, // 报告是否按照百分比报告
|
||||
false, // 不回发接收长度
|
||||
true, // 检查是否超时
|
||||
failedString // 异常时的附加文本描述
|
||||
);
|
||||
|
||||
if(!value.Result)
|
||||
{
|
||||
return value2;
|
||||
}
|
||||
|
||||
value2.Content = value.Content;
|
||||
|
||||
Log.i("准备检查令牌", "ReceiveAndCheckBytes: ");
|
||||
|
||||
// 检查令牌
|
||||
if (!CheckTokenPermission(socket, value.Content, KeyToken, result))
|
||||
{
|
||||
Log.i("令牌检查失败", "ReceiveAndCheckBytes: ");
|
||||
result.Message = StringResources.TokenCheckFailed;
|
||||
return value2;
|
||||
}
|
||||
|
||||
// 接收内容
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0]=value.Content[28];
|
||||
buffer[1]=value.Content[29];
|
||||
buffer[2]=value.Content[30];
|
||||
buffer[3]=value.Content[31];
|
||||
int contentLength = Utilities.bytes2Int(buffer);
|
||||
|
||||
Log.i("准备接收内容,长度为:"+contentLength, "ReceiveAndCheckBytes: ");
|
||||
|
||||
value =ReceiveBytesFromSocket(
|
||||
socket, // 套接字
|
||||
contentLength, // 内容数据长度
|
||||
result, // 结果消息对象
|
||||
receiveReport, // 接收进度报告委托
|
||||
true, // 按照百分比进行报告数据
|
||||
true, // 回发已经接收的数据长度
|
||||
false, // 不进行超时检查
|
||||
failedString // 异常时附加的文本描述
|
||||
);
|
||||
|
||||
if(!value.Result)
|
||||
{
|
||||
return value2;
|
||||
}
|
||||
Log.i("内容接收成功", "ReceiveAndCheckBytes: ");
|
||||
|
||||
value2.Content2 = NetSupport.CommandAnalysis(value2.Content, value.Content);
|
||||
value2.Result=true;
|
||||
return value2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 从网络中接收一个字符串数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="customer">接收的用户数据</param>
|
||||
/// <param name="receive">接收的字节数据</param>
|
||||
/// <param name="result">结果信息对象</param>
|
||||
/// <param name="receiveReport">接收数据时的进度报告</param>
|
||||
/// <param name="failedString">失败时记录日志的字符串</param>
|
||||
/// <returns></returns>
|
||||
protected boolWithIntString ReceiveStringFromSocket(
|
||||
Socket socket,
|
||||
OperateResult result,
|
||||
ProgressReport receiveReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
boolWithIntString valueString = new boolWithIntString();
|
||||
|
||||
boolWith2Bytes value2Bytes = ReceiveAndCheckBytes(socket,result, receiveReport, failedString);
|
||||
|
||||
if (!value2Bytes.Result)
|
||||
{
|
||||
return valueString;
|
||||
}
|
||||
|
||||
// check
|
||||
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0]=value2Bytes.Content[0];
|
||||
buffer[1]=value2Bytes.Content[1];
|
||||
buffer[2]=value2Bytes.Content[2];
|
||||
buffer[3]=value2Bytes.Content[3];
|
||||
if (Utilities.bytes2Int(buffer) != HslCommunicationCode.Hsl_Protocol_User_String)
|
||||
{
|
||||
result.Message = "数据头校验失败!";
|
||||
LogUtil.LogE("ReceiveStringFromSocket","数据头校验失败!");
|
||||
CloseSocket(socket);
|
||||
return valueString;
|
||||
}
|
||||
|
||||
buffer[0]=value2Bytes.Content[4];
|
||||
buffer[1]=value2Bytes.Content[5];
|
||||
buffer[2]=value2Bytes.Content[6];
|
||||
buffer[3]=value2Bytes.Content[7];
|
||||
// 分析数据
|
||||
valueString.DataInt = Utilities.bytes2Int(buffer);
|
||||
valueString.DataString = Utilities.byte2String(value2Bytes.Content2);
|
||||
valueString.Result = true;
|
||||
return valueString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 从网络中接收一串字节数据,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">套接字</param>
|
||||
/// <param name="customer">接收的用户数据</param>
|
||||
/// <param name="data">接收的字节数据</param>
|
||||
/// <param name="result">结果信息对象</param>
|
||||
/// <param name="failedString">失败时记录日志的字符串</param>
|
||||
/// <returns></returns>
|
||||
protected boolWithIntByte ReceiveContentFromSocket(
|
||||
Socket socket,
|
||||
OperateResult result,
|
||||
ProgressReport receiveReport,
|
||||
String failedString
|
||||
)
|
||||
{
|
||||
|
||||
boolWithIntByte value = new boolWithIntByte();
|
||||
|
||||
boolWith2Bytes value2Bytes = ReceiveAndCheckBytes(socket,result,null, failedString);
|
||||
|
||||
if (!value2Bytes.Result)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0]=value2Bytes.Content[0];
|
||||
buffer[1]=value2Bytes.Content[1];
|
||||
buffer[2]=value2Bytes.Content[2];
|
||||
buffer[3]=value2Bytes.Content[3];
|
||||
if (Utilities.bytes2Int(buffer) != HslCommunicationCode.Hsl_Protocol_User_String)
|
||||
{
|
||||
result.Message = "数据头校验失败!";
|
||||
LogUtil.LogE("ReceiveContentFromSocket","数据头校验失败!");
|
||||
CloseSocket(socket);
|
||||
return value;
|
||||
}
|
||||
|
||||
buffer[0]=value2Bytes.Content[4];
|
||||
buffer[1]=value2Bytes.Content[5];
|
||||
buffer[2]=value2Bytes.Content[6];
|
||||
buffer[3]=value2Bytes.Content[7];
|
||||
// 分析数据
|
||||
value.DataInt = Utilities.bytes2Int(buffer);
|
||||
value.Content = value2Bytes.Content2;
|
||||
value.Result = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 从套接字中接收文件头信息
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <param name="size"></param>
|
||||
/// <param name="filetag"></param>
|
||||
/// <param name="fileupload"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="failedString"></param>
|
||||
/// <returns></returns>
|
||||
protected bool ReceiveFileHeadFromSocket(
|
||||
Socket socket,
|
||||
out string filename,
|
||||
out long size,
|
||||
out string filetag,
|
||||
out string fileupload,
|
||||
OperateResult result,
|
||||
string failedString = null
|
||||
)
|
||||
{
|
||||
// 先接收文件头信息
|
||||
if (!ReceiveStringFromSocket(socket, out int customer, out string filehead, result, null, failedString))
|
||||
{
|
||||
filename = null;
|
||||
size = 0;
|
||||
filetag = null;
|
||||
fileupload = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断文件是否存在
|
||||
if (customer == 0)
|
||||
{
|
||||
LogNet?.WriteWarn("对方文件不存在,无法接收!");
|
||||
result.Message = StringResources.FileNotExist;
|
||||
filename = null;
|
||||
size = 0;
|
||||
filetag = null;
|
||||
fileupload = null;
|
||||
socket?.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 提取信息
|
||||
Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(filehead);
|
||||
filename = SoftBasic.GetValueFromJsonObject(json, "FileName", "");
|
||||
size = SoftBasic.GetValueFromJsonObject(json, "FileSize", 0L);
|
||||
filetag = SoftBasic.GetValueFromJsonObject(json, "FileTag", "");
|
||||
fileupload = SoftBasic.GetValueFromJsonObject(json, "FileUpload", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 从网络中接收一个文件,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="savename">接收文件后保存的文件名</param>
|
||||
/// <param name="filename">文件在对方电脑上的文件名</param>
|
||||
/// <param name="size">文件大小</param>
|
||||
/// <param name="filetag">文件的标识</param>
|
||||
/// <param name="fileupload">文件的上传人</param>
|
||||
/// <param name="result">结果信息对象</param>
|
||||
/// <param name="receiveReport">接收进度报告</param>
|
||||
/// <param name="failedString">失败时的记录日志字符串</param>
|
||||
/// <returns></returns>
|
||||
protected bool ReceiveFileFromSocket(
|
||||
Socket socket,
|
||||
string savename,
|
||||
out string filename,
|
||||
out long size,
|
||||
out string filetag,
|
||||
out string fileupload,
|
||||
OperateResult result,
|
||||
Action<long, long> receiveReport,
|
||||
string failedString = null
|
||||
)
|
||||
{
|
||||
// 先接收文件头信息
|
||||
if (!ReceiveFileHeadFromSocket(
|
||||
socket,
|
||||
out filename,
|
||||
out size,
|
||||
out filetag,
|
||||
out fileupload,
|
||||
result,
|
||||
failedString
|
||||
))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//// 先接收文件头信息
|
||||
//if (!ReceiveStringFromSocket(socket, out int customer, out string filehead, result, null, failedString))
|
||||
//{
|
||||
// filename = null;
|
||||
// size = 0;
|
||||
// filetag = null;
|
||||
// fileupload = null;
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//// 判断文件是否存在
|
||||
//if (customer == 0)
|
||||
//{
|
||||
// LogNet?.WriteWarn("对方文件不存在,无法接收!");
|
||||
// result.Message = StringResources.FileNotExist;
|
||||
// filename = null;
|
||||
// size = 0;
|
||||
// filetag = null;
|
||||
// fileupload = null;
|
||||
// socket?.Close();
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//// 提取信息
|
||||
//Newtonsoft.Json.Linq.JObject json = Newtonsoft.Json.Linq.JObject.Parse(filehead);
|
||||
//filename = SoftBasic.GetValueFromJsonObject(json, "FileName", "");
|
||||
//size = SoftBasic.GetValueFromJsonObject(json, "FileSize", 0L);
|
||||
//filetag = SoftBasic.GetValueFromJsonObject(json, "FileTag", "");
|
||||
//fileupload = SoftBasic.GetValueFromJsonObject(json, "FileUpload", "");
|
||||
|
||||
// 接收文件消息
|
||||
if (!ReceiveFileSteamFromSocket(socket, savename, size, receiveReport, result, failedString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [自校验] 从网络中接收一个文件,写入数据流,如果结果异常,则结束通讯
|
||||
/// </summary>
|
||||
/// <param name="socket">网络套接字</param>
|
||||
/// <param name="stream">等待写入的数据流</param>
|
||||
/// <param name="filename">文件在对方电脑上的文件名</param>
|
||||
/// <param name="size">文件大小</param>
|
||||
/// <param name="filetag">文件的标识</param>
|
||||
/// <param name="fileupload">文件的上传人</param>
|
||||
/// <param name="result">结果信息对象</param>
|
||||
/// <param name="receiveReport">接收进度报告</param>
|
||||
/// <param name="failedString">失败时的记录日志字符串</param>
|
||||
/// <returns></returns>
|
||||
protected bool ReceiveFileFromSocket(
|
||||
Socket socket,
|
||||
Stream stream,
|
||||
out string filename,
|
||||
out long size,
|
||||
out string filetag,
|
||||
out string fileupload,
|
||||
OperateResult result,
|
||||
Action<long, long> receiveReport,
|
||||
string failedString = null
|
||||
)
|
||||
{
|
||||
// 先接收文件头信息
|
||||
if (!ReceiveFileHeadFromSocket(
|
||||
socket,
|
||||
out filename,
|
||||
out size,
|
||||
out filetag,
|
||||
out fileupload,
|
||||
result,
|
||||
failedString
|
||||
))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
NetSupport.WriteStreamFromSocket(socket, stream, size, receiveReport, true);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Message = ex.Message;
|
||||
socket?.Close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
import com.example.HslCommunication.Core.Types.HslTimeOut;
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
import java.io.DataInputStream;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class NetSupport {
|
||||
|
||||
private static final int SocketBufferSize = 4096;
|
||||
|
||||
|
||||
|
||||
public static void ThreadPoolCheckConnect(HslTimeOut timeout, int millisecond) {
|
||||
while (!timeout.IsSuccessful) {
|
||||
if ((new Date().getTime() - timeout.StartTime.getTime()) > millisecond) {
|
||||
// 连接超时或是验证超时
|
||||
if (!timeout.IsSuccessful) {
|
||||
try {
|
||||
if (timeout.WorkSocket != null) {
|
||||
timeout.WorkSocket.close();
|
||||
}
|
||||
} catch (java.io.IOException ex) {
|
||||
// 不处理,放弃
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean IsTwoBytesEquel(byte[] b1, int start1, byte[] b2, int start2, int length) {
|
||||
if (b1 == null || b2 == null) return false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (b1[i + start1] != b2[i + start2]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean CheckTokenEquel(byte[] head, UUID token)
|
||||
{
|
||||
return IsTwoBytesEquel(head, 12, Utilities.UUID2Byte(token), 0, 16);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] ReadBytesFromSocket(Socket socket, int receive, ProgressReport report, boolean reportByPercent, boolean response) throws java.io.IOException
|
||||
{
|
||||
byte[] bytes_receive = new byte[receive];
|
||||
int count_receive = 0;
|
||||
long percent = 0;
|
||||
|
||||
DataInputStream input = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
|
||||
|
||||
while (count_receive < receive) {
|
||||
// 分割成4KB来接收数据
|
||||
int receive_length = 0;
|
||||
if ((receive - count_receive) >= SocketBufferSize) {
|
||||
receive_length = SocketBufferSize;
|
||||
} else {
|
||||
receive_length = (receive - count_receive);
|
||||
}
|
||||
|
||||
count_receive += input.read(bytes_receive, count_receive, receive_length);
|
||||
|
||||
if (reportByPercent) {
|
||||
long percentCurrent = (long) count_receive * 100 / receive;
|
||||
if (percent != percentCurrent) {
|
||||
percent = percentCurrent;
|
||||
// 报告进度
|
||||
if (report != null) report.Report(count_receive, receive);
|
||||
}
|
||||
} else {
|
||||
// 报告进度
|
||||
if (report != null) report.Report(count_receive, receive);
|
||||
}
|
||||
|
||||
// 回发进度
|
||||
if (response) output.write(Utilities.long2Bytes((long) count_receive));
|
||||
}
|
||||
|
||||
return bytes_receive;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] ReadBytesFromSocket(Socket socket, int receive) throws java.io.IOException {
|
||||
return ReadBytesFromSocket(socket, receive, null, false, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 读取套接字并且写入流
|
||||
/// </summary>
|
||||
/// <param name="stream">文件流</param>
|
||||
/// <param name="socket">连接的套接字</param>
|
||||
/// <param name="length">返回的文件长度</param>
|
||||
/// <param name="report">发送的进度报告</param>
|
||||
/// <param name="reportByPercent"></param>
|
||||
public static void WriteStreamFromSocket(Socket socket, OutputStream stream, long receive, ProgressReport report, boolean reportByPercent) throws java.io.IOException
|
||||
{
|
||||
byte[] buffer = new byte[SocketBufferSize];
|
||||
long count_receive = 0;
|
||||
long percent = 0;
|
||||
|
||||
DataInputStream input = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
|
||||
|
||||
while (count_receive < receive)
|
||||
{
|
||||
// 分割成4KB来接收数据
|
||||
int current = input.read(buffer, 0, SocketBufferSize);
|
||||
|
||||
count_receive += current;
|
||||
stream.write(buffer, 0, current);
|
||||
if (reportByPercent)
|
||||
{
|
||||
long percentCurrent = count_receive * 100 / receive;
|
||||
if (percent != percentCurrent)
|
||||
{
|
||||
percent = percentCurrent;
|
||||
// 报告进度
|
||||
if (report != null) report.Report(count_receive, receive);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 报告进度
|
||||
if (report != null) report.Report(count_receive, receive);
|
||||
}
|
||||
// 回发进度
|
||||
output.write(Utilities.long2Bytes(count_receive));
|
||||
}
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 读取流并将数据写入socket
|
||||
/// </summary>
|
||||
/// <param name="stream">文件流</param>
|
||||
/// <param name="socket">连接的套接字</param>
|
||||
/// <param name="length">返回的文件长度</param>
|
||||
/// <param name="report">发送的进度报告</param>
|
||||
/// <param name="reportByPercent"></param>
|
||||
public static void WriteSocketFromStream(Socket socket, InputStream stream, long length, ProgressReport report, boolean reportByPercent) throws java.io.IOException
|
||||
{
|
||||
byte[] buffer = new byte[SocketBufferSize];
|
||||
long count_send = 0;
|
||||
long percent = 0;
|
||||
|
||||
DataInputStream input = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
|
||||
|
||||
while (count_send < length)
|
||||
{
|
||||
int count = stream.read(buffer, 0, SocketBufferSize);
|
||||
count_send += count;
|
||||
|
||||
|
||||
output.write(buffer, 0, count);
|
||||
|
||||
while (count_send != Utilities.bytes2Long(ReadBytesFromSocket(socket, 8)));
|
||||
|
||||
long received = count_send;
|
||||
|
||||
if (reportByPercent)
|
||||
{
|
||||
long percentCurrent = received * 100 / length;
|
||||
if (percent != percentCurrent)
|
||||
{
|
||||
percent = percentCurrent;
|
||||
// 报告进度
|
||||
if (report != null) report.Report(received, length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 报告进度
|
||||
if (report != null) report.Report(received, length);
|
||||
}
|
||||
|
||||
// 双重接收验证
|
||||
if (count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void CheckSendBytesReceived(Socket socket, long length, ProgressReport report, boolean reportByPercent) throws java.io.IOException
|
||||
{
|
||||
long remoteNeedReceive = 0;
|
||||
long percent = 0;
|
||||
|
||||
// 确认服务器的数据是否接收完成
|
||||
while (remoteNeedReceive < length)
|
||||
{
|
||||
remoteNeedReceive = Utilities.bytes2Long(ReadBytesFromSocket(socket, 8));
|
||||
if (reportByPercent)
|
||||
{
|
||||
long percentCurrent = remoteNeedReceive * 100 / length;
|
||||
if (percent != percentCurrent)
|
||||
{
|
||||
percent = percentCurrent;
|
||||
// 报告进度
|
||||
if (report != null) report.Report(remoteNeedReceive, length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 报告进度
|
||||
if (report != null) report.Report(remoteNeedReceive, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
发送字节数据的最终命令
|
||||
|
||||
*/
|
||||
|
||||
public static byte[] CommandBytes(int customer, UUID token, byte[] data)
|
||||
{
|
||||
return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_Bytes, customer, token, data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
生成发送文本数据的最终命令
|
||||
|
||||
*/
|
||||
|
||||
public static byte[] CommandBytes(int customer, UUID token, String data)
|
||||
{
|
||||
if (data == null) return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_String, customer, token, null);
|
||||
else return CommandBytes(HslCommunicationCode.Hsl_Protocol_User_String, customer, token, Utilities.string2Byte(data));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
生成最终的发送命令
|
||||
|
||||
*/
|
||||
|
||||
public static byte[] CommandBytes(int command, int customer, UUID token, byte[] data)
|
||||
{
|
||||
byte[] _temp = null;
|
||||
int _zipped = HslCommunicationCode.Hsl_Protocol_NoZipped;
|
||||
int _sendLength = 0;
|
||||
if (data == null)
|
||||
{
|
||||
_temp = new byte[HslCommunicationCode.HeadByteLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
// 加密
|
||||
data = HslSecurity.ByteEncrypt(data);
|
||||
if (data.length > 10240)
|
||||
{
|
||||
// 10K以上的数据,进行数据压缩
|
||||
data = HslZipped.CompressBytes(data);
|
||||
_zipped = HslCommunicationCode.Hsl_Protocol_Zipped;
|
||||
}
|
||||
_temp = new byte[HslCommunicationCode.HeadByteLength + data.length];
|
||||
_sendLength = data.length;
|
||||
}
|
||||
|
||||
Utilities.int2Bytes(command);
|
||||
|
||||
System.arraycopy(Utilities.int2Bytes(command),0,_temp,0,4);
|
||||
System.arraycopy(Utilities.int2Bytes(customer),0,_temp,4,4);
|
||||
System.arraycopy(Utilities.int2Bytes(_zipped),0,_temp,8,4);
|
||||
System.arraycopy(Utilities.UUID2Byte(token),0,_temp,12,16);
|
||||
System.arraycopy(Utilities.int2Bytes(_sendLength),0,_temp,28,4);
|
||||
if (_sendLength > 0)
|
||||
{
|
||||
System.arraycopy(data,0,_temp,32,_sendLength);
|
||||
}
|
||||
return _temp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
从接收的数据命令开始解析
|
||||
|
||||
*/
|
||||
|
||||
public static byte[] CommandAnalysis(byte[] head, byte[] content)
|
||||
{
|
||||
if (content != null)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0] = head[8];
|
||||
buffer[1] = head[9];
|
||||
buffer[2] = head[10];
|
||||
buffer[3] = head[11];
|
||||
|
||||
int _zipped = Utilities.bytes2Int(buffer);
|
||||
// 先进行解压
|
||||
if (_zipped == HslCommunicationCode.Hsl_Protocol_Zipped)
|
||||
{
|
||||
content = HslZipped.Decompress(content);
|
||||
}
|
||||
// 进行解密
|
||||
return HslSecurity.ByteDecrypt(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.HslCommunication.Core.Net;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
|
||||
public abstract class ProgressReport {
|
||||
|
||||
|
||||
public void Report(long current,long totle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.HslCommunication.Core.Types;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class HslTimeOut {
|
||||
|
||||
|
||||
public HslTimeOut()
|
||||
{
|
||||
StartTime = new Date();
|
||||
IsSuccessful = false;
|
||||
}
|
||||
|
||||
public Date StartTime=null;
|
||||
|
||||
public boolean IsSuccessful=false;
|
||||
|
||||
public int DelayTime=5000;
|
||||
|
||||
public Socket WorkSocket=null;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.example.HslCommunication.Core.Types;
|
||||
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public final class NetHandle {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化一个暗号对象
|
||||
/// </summary>
|
||||
public NetHandle(int value)
|
||||
{
|
||||
byte[] buffer = Utilities.int2Bytes(value);
|
||||
|
||||
m_CodeMajor = buffer[3];
|
||||
m_CodeMinor = buffer[2];
|
||||
m_CodeIdentifier = Utilities.byte2Short(buffer,0);
|
||||
|
||||
|
||||
m_CodeValue = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据三个值来初始化暗号对象
|
||||
/// </summary>
|
||||
/// <param name="major">主暗号</param>
|
||||
/// <param name="minor">次暗号</param>
|
||||
/// <param name="identifier">暗号编号</param>
|
||||
public NetHandle(int major, int minor, int identifier)
|
||||
{
|
||||
m_CodeValue = 0;
|
||||
|
||||
byte[] buffer_major=Utilities.int2Bytes(major);
|
||||
byte[] buffer_minor=Utilities.int2Bytes(minor);
|
||||
byte[] buffer_identifier=Utilities.int2Bytes(identifier);
|
||||
|
||||
m_CodeMajor = buffer_major[0];
|
||||
m_CodeMinor = buffer_minor[0];
|
||||
m_CodeIdentifier = Utilities.byte2Short(buffer_identifier,0);
|
||||
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[3] = m_CodeMajor;
|
||||
buffer[2] = m_CodeMinor;
|
||||
buffer[1] = buffer_identifier[1];
|
||||
buffer[0] = buffer_identifier[0];
|
||||
|
||||
m_CodeValue = Utilities.bytes2Int(buffer);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 完整的暗号值
|
||||
/// </summary>
|
||||
private int m_CodeValue;
|
||||
|
||||
/// <summary>
|
||||
/// 主暗号分类0-255
|
||||
/// </summary>
|
||||
private byte m_CodeMajor;
|
||||
|
||||
/// <summary>
|
||||
/// 次要的暗号分类0-255
|
||||
/// </summary>
|
||||
private byte m_CodeMinor;
|
||||
|
||||
/// <summary>
|
||||
/// 暗号的编号分类0-65535
|
||||
/// </summary>
|
||||
private short m_CodeIdentifier;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 完整的暗号值
|
||||
/// </summary>
|
||||
public int get_CodeValue(){
|
||||
return m_CodeValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主暗号分类0-255
|
||||
/// </summary>
|
||||
public byte get_CodeMajor() {
|
||||
return m_CodeMajor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 次要的暗号分类0-255
|
||||
/// </summary>
|
||||
public byte get_CodeMinor() {
|
||||
return m_CodeMinor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暗号的编号分类0-65535
|
||||
/// </summary>
|
||||
public short get_CodeIdentifier() {
|
||||
return m_CodeIdentifier;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.example.HslCommunication.Core.Types;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class OperateResult {
|
||||
|
||||
/// <summary>
|
||||
/// 指示本次访问是否成功
|
||||
/// </summary>
|
||||
public boolean IsSuccess =false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 具体的错误描述
|
||||
/// </summary>
|
||||
public String Message = "Unknown Errors";
|
||||
/// <summary>
|
||||
/// 具体的错误代码
|
||||
/// </summary>
|
||||
public int ErrorCode = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// 消息附带的额外信息
|
||||
/// </summary>
|
||||
public Object Tag =null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取错误代号及文本描述
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public String ToMessageShowString()
|
||||
{
|
||||
return "错误代码:"+ErrorCode +"\r\n错误信息:"+Message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.example.HslCommunication.Core.Types;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
public class OperateResultBytes extends OperateResult {
|
||||
public byte[] Content =null;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.HslCommunication.Core.Types;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public class OperateResultString extends OperateResult {
|
||||
public String Content = null;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/1.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public class Utilities {
|
||||
|
||||
public static byte[] int2Bytes(int num) {
|
||||
byte[] byteNum = new byte[4];
|
||||
for (int ix = 0; ix < 4; ++ix) {
|
||||
int offset = 32 - (ix + 1) * 8;
|
||||
byteNum[3-ix] = (byte) ((num >> offset) & 0xff);
|
||||
}
|
||||
return byteNum;
|
||||
}
|
||||
|
||||
public static int bytes2Int(byte[] byteNum) {
|
||||
int num = 0;
|
||||
for (int ix = 0; ix < 4; ++ix) {
|
||||
num <<= 8;
|
||||
num |= (byteNum[3-ix] & 0xff);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static byte int2OneByte(int num) {
|
||||
return (byte) (num & 0x000000ff);
|
||||
}
|
||||
|
||||
public static int oneByte2Int(byte byteNum) {
|
||||
//针对正数的int
|
||||
return byteNum > 0 ? byteNum : (128 + (128 + byteNum));
|
||||
}
|
||||
|
||||
public static byte[] long2Bytes(long num) {
|
||||
byte[] byteNum = new byte[8];
|
||||
for (int ix = 0; ix < 8; ++ix) {
|
||||
int offset = 64 - (ix + 1) * 8;
|
||||
byteNum[7-ix] = (byte) ((num >> offset) & 0xff);
|
||||
}
|
||||
return byteNum;
|
||||
}
|
||||
|
||||
public static long bytes2Long(byte[] byteNum) {
|
||||
long num = 0;
|
||||
for (int ix = 0; ix < 8; ++ix) {
|
||||
num <<= 8;
|
||||
num |= (byteNum[7-ix] & 0xff);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public static UUID Byte2UUID(byte[] data) {
|
||||
if (data.length != 16) {
|
||||
throw new IllegalArgumentException("Invalid UUID byte[]");
|
||||
}
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
msb = (msb << 8) | (data[i] & 0xff);
|
||||
for (int i = 8; i < 16; i++)
|
||||
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||
|
||||
return new UUID(msb, lsb);
|
||||
}
|
||||
|
||||
public static byte[] UUID2Byte(UUID uuid) {
|
||||
ByteArrayOutputStream ba = new ByteArrayOutputStream(16);
|
||||
DataOutputStream da = new DataOutputStream(ba);
|
||||
try {
|
||||
da.writeLong(uuid.getMostSignificantBits());
|
||||
da.writeLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[] buffer = ba.toByteArray();
|
||||
// 进行错位
|
||||
byte temp=buffer[0];
|
||||
buffer[0] = buffer[3];
|
||||
buffer[3] =temp;
|
||||
temp=buffer[1];
|
||||
buffer[1]=buffer[2];
|
||||
buffer[2]=temp;
|
||||
|
||||
temp = buffer[4];
|
||||
buffer[4]=buffer[5];
|
||||
buffer[5] =temp;
|
||||
|
||||
temp = buffer[6];
|
||||
buffer[6]=buffer[7];
|
||||
buffer[7] =temp;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static short byte2Short(byte[] b, int index) {
|
||||
return (short) (((b[index + 0] << 8) | b[index + 1] & 0xff));
|
||||
}
|
||||
|
||||
|
||||
public static byte[] short2Byte(short s) {
|
||||
byte[] targets = new byte[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int offset = (targets.length - 1 - i) * 8;
|
||||
targets[1-i] = (byte) ((s >>> offset) & 0xff);
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
public static byte[] string2Byte(String str) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] byteArray;
|
||||
try {
|
||||
byteArray = str.getBytes("unicode");
|
||||
} catch (Exception ex) {
|
||||
byteArray = str.getBytes();
|
||||
}
|
||||
|
||||
for(int i=0;i<byteArray.length;i++)
|
||||
{
|
||||
byte temp=byteArray[i];
|
||||
byteArray[i]=byteArray[i+1];
|
||||
byteArray[i+1] =temp;
|
||||
i++;
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
public static String byte2String(byte[] byteArray) {
|
||||
if (byteArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < byteArray.length; i++) {
|
||||
byte temp = byteArray[i];
|
||||
byteArray[i] = byteArray[i + 1];
|
||||
byteArray[i + 1] = temp;
|
||||
i++;
|
||||
}
|
||||
String str;
|
||||
try {
|
||||
str = new String(byteArray, "unicode");
|
||||
} catch (Exception ex) {
|
||||
str = new String(byteArray);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
public static String bytes2HexString(byte[] bytes) {
|
||||
char[] buf = new char[bytes.length * 2];
|
||||
int index = 0;
|
||||
for(byte b : bytes) { // 利用位运算进行转换,可以看作方法一的变种
|
||||
buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
|
||||
buf[index++] = HEX_CHAR[b & 0xf];
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public class boolWith2Bytes extends boolWithBytes {
|
||||
public byte[] Content2=null;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
|
||||
public class boolWithBytes extends boolWithNone {
|
||||
|
||||
|
||||
public byte[] Content=null;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public class boolWithIntByte extends boolWithBytes {
|
||||
public int DataInt=0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public class boolWithIntString extends boolWithNone {
|
||||
|
||||
|
||||
public int DataInt=0;
|
||||
|
||||
|
||||
public String DataString=null;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/3.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 结果类的基础,提供一个boolen
|
||||
*
|
||||
*
|
||||
* */
|
||||
|
||||
public class boolWithNone {
|
||||
|
||||
/*
|
||||
返回真还是否
|
||||
*/
|
||||
public boolean Result = false;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/3.
|
||||
*/
|
||||
|
||||
public class boolWithSiemens extends boolWithNone {
|
||||
|
||||
|
||||
public byte type=0;
|
||||
|
||||
public int startAddress=0;
|
||||
|
||||
public short dbAddress=0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
*/
|
||||
|
||||
public class boolWithSocket extends boolWithNone {
|
||||
public Socket Socket=null;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.example.HslCommunication.Core.Utilities;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public class boolWithString extends boolWithNone {
|
||||
|
||||
public String Content=null;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.example.HslCommunication.Enthernet;
|
||||
|
||||
import com.example.HslCommunication.Core.Net.HslCommunicationCode;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
*/
|
||||
|
||||
public class AsyncStateOne {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 实例化一个对象
|
||||
/// </summary>
|
||||
public AsyncStateOne() {
|
||||
ClientUniqueID = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// IP地址
|
||||
/// </summary>
|
||||
private String IpAddress = "";
|
||||
|
||||
public String getIpAddress() {
|
||||
return IpAddress;
|
||||
}
|
||||
|
||||
private void setIpAddress(String ipAddress) {
|
||||
IpAddress = ipAddress;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
端口号
|
||||
*/
|
||||
private int IpPort = 10000;
|
||||
|
||||
public int getIpPort() {
|
||||
return IpPort;
|
||||
}
|
||||
|
||||
private void setIpPort(int ipPort) {
|
||||
IpPort = ipPort;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
登录的别名
|
||||
*/
|
||||
private String LoginAlias = "";
|
||||
|
||||
public String getLoginAlias() {
|
||||
return LoginAlias;
|
||||
}
|
||||
|
||||
public void setLoginAlias(String loginAlias) {
|
||||
LoginAlias = loginAlias;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
心跳验证的时间点
|
||||
*/
|
||||
private Date HeartTime=new Date();
|
||||
public Date getHeartTime() {
|
||||
return HeartTime;
|
||||
}
|
||||
|
||||
public void setHeartTime(Date heartTime) {
|
||||
HeartTime = heartTime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
客户端类别
|
||||
*/
|
||||
private String ClientType="";
|
||||
public void setClientType(String clientType) {
|
||||
ClientType = clientType;
|
||||
}
|
||||
|
||||
|
||||
public String getClientType() {
|
||||
return ClientType;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
客户端的唯一标识
|
||||
*/
|
||||
private String ClientUniqueID="";
|
||||
public String getClientUniqueID() {
|
||||
return ClientUniqueID;
|
||||
}
|
||||
|
||||
public void setClientUniqueID(String clientUniqueID) {
|
||||
ClientUniqueID = clientUniqueID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 指令头缓存
|
||||
/// </summary>
|
||||
byte[] BytesHead = new byte[HslCommunicationCode.HeadByteLength];
|
||||
/// <summary>
|
||||
/// 已经接收的指令头长度
|
||||
/// </summary>
|
||||
int AlreadyReceivedHead = 0;
|
||||
/// <summary>
|
||||
/// 数据内容缓存
|
||||
/// </summary>
|
||||
byte[] BytesContent = null;
|
||||
/// <summary>
|
||||
/// 已经接收的数据内容长度
|
||||
/// </summary>
|
||||
int AlreadyReceivedContent = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 清除本次的接收内容
|
||||
/// </summary>
|
||||
void Clear() {
|
||||
BytesHead = new byte[HslCommunicationCode.HeadByteLength];
|
||||
AlreadyReceivedHead = 0;
|
||||
BytesContent = null;
|
||||
AlreadyReceivedContent = 0;
|
||||
}
|
||||
|
||||
|
||||
Socket WorkSocket=null;
|
||||
}
|
||||
@@ -0,0 +1,442 @@
|
||||
package com.example.HslCommunication.Enthernet;
|
||||
|
||||
import com.example.HslCommunication.Core.Net.HslCommunicationCode;
|
||||
import com.example.HslCommunication.Core.Net.NetShareBase;
|
||||
import com.example.HslCommunication.Core.Net.NetSupport;
|
||||
import com.example.HslCommunication.Core.Types.NetHandle;
|
||||
import com.example.HslCommunication.Core.Types.OperateResult;
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithSocket;
|
||||
import com.example.HslCommunication.Log.LogUtil;
|
||||
import com.example.HslCommunication.Resources.StringResources;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
*/
|
||||
|
||||
public class NetComplexClient extends NetShareBase {
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 客户端的核心连接块
|
||||
/// </summary>
|
||||
private AsyncStateOne stateone = new AsyncStateOne();
|
||||
/// <summary>
|
||||
/// 客户端系统是否启动
|
||||
/// </summary>
|
||||
public boolean Is_Client_Start = false;
|
||||
|
||||
/// <summary>
|
||||
/// 重连接失败的次数
|
||||
/// </summary>
|
||||
public int Connect_Failed_Count = 0;
|
||||
/// <summary>
|
||||
/// 指示客户端是否处于正在连接服务器中
|
||||
/// </summary>
|
||||
private boolean Is_Client_Connecting = false;
|
||||
/// <summary>
|
||||
/// 登录服务器的判断锁
|
||||
/// </summary>
|
||||
private Object lock_connecting = new Object();
|
||||
/// <summary>
|
||||
/// 客户端登录的标识名称,可以为ID号,也可以为登录名
|
||||
/// </summary>
|
||||
public String ClientAlias = "";
|
||||
/// <summary>
|
||||
/// 远程服务器的IP地址和端口
|
||||
/// </summary>
|
||||
public String ServerIp = "127.0.0.1";
|
||||
/*
|
||||
远程服务器的端口
|
||||
*/
|
||||
public int ServerPort = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// 服务器的时间,自动实现和服务器同步
|
||||
/// </summary>
|
||||
private Date ServerTime = new Date();
|
||||
/// <summary>
|
||||
/// 系统与服务器的延时时间,单位毫秒
|
||||
/// </summary>
|
||||
private int DelayTime =0;
|
||||
|
||||
|
||||
|
||||
public void LoginSuccess()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void LoginFailed(int times)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void MessageAlerts(String msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void BeforReConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AcceptString(NetHandle handle, String msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void AcceptByte( NetHandle handle, byte[] msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean IsQuie = false;
|
||||
|
||||
/// <summary>
|
||||
/// 关闭该客户端引擎
|
||||
/// </summary>
|
||||
public void ClientClose() {
|
||||
IsQuie = true;
|
||||
if (Is_Client_Start)
|
||||
SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Client_Quit, 0, KeyToken, null));
|
||||
|
||||
if (thread_heart_check != null) thread_heart_check.interrupt();
|
||||
Is_Client_Start = false;
|
||||
|
||||
|
||||
ThreadSleep(10);
|
||||
|
||||
CloseSocket(stateone.WorkSocket);
|
||||
LogUtil.LogD("ClientClose","Client Close.");
|
||||
}
|
||||
/// <summary>
|
||||
/// 启动客户端引擎,连接服务器系统
|
||||
/// </summary>
|
||||
public void ClientStart()
|
||||
{
|
||||
if (Is_Client_Start) return;
|
||||
Thread thread_login = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ThreadLogin();
|
||||
}
|
||||
});
|
||||
thread_login.start();
|
||||
LogUtil.LogD("ClientStart","Client Start.");
|
||||
|
||||
if (thread_heart_check == null)
|
||||
{
|
||||
thread_heart_check = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ThreadHeartCheck();
|
||||
}
|
||||
});
|
||||
thread_heart_check.start();
|
||||
}
|
||||
}
|
||||
private void ThreadLogin()
|
||||
{
|
||||
synchronized (lock_connecting)
|
||||
{
|
||||
if (Is_Client_Connecting) return;
|
||||
Is_Client_Connecting = true;
|
||||
}
|
||||
|
||||
|
||||
if (Connect_Failed_Count == 0)
|
||||
{
|
||||
MessageAlerts("正在连接服务器...");
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 10;
|
||||
while (count > 0)
|
||||
{
|
||||
if (IsQuie) return;
|
||||
MessageAlerts("连接断开,等待" + count-- + "秒后重新连接");
|
||||
ThreadSleep(1000);
|
||||
}
|
||||
MessageAlerts("正在尝试第" + Connect_Failed_Count + "次连接服务器...");
|
||||
}
|
||||
|
||||
|
||||
stateone.setHeartTime(new Date());
|
||||
LogUtil.LogD("ThreadLogin","Begin Connect Server, Times: " + Connect_Failed_Count);
|
||||
|
||||
|
||||
OperateResult result = new OperateResult();
|
||||
|
||||
Socket socket=null;
|
||||
boolWithSocket valueSocket = CreateSocketAndConnect(ServerIp,ServerPort,result);
|
||||
if(!valueSocket.Result)
|
||||
{
|
||||
Connect_Failed_Count++;
|
||||
Is_Client_Connecting = false;
|
||||
LoginFailed(Connect_Failed_Count);
|
||||
LogUtil.LogW("ThreadLogin","Connected Failed, Times: " + Connect_Failed_Count);
|
||||
// 连接失败,重新连接服务器
|
||||
ReconnectServer();
|
||||
return;
|
||||
}
|
||||
|
||||
socket = valueSocket.Socket;
|
||||
|
||||
// 连接成功,发送数据信息
|
||||
if(!SendStringAndCheckReceive(
|
||||
socket,
|
||||
1,
|
||||
ClientAlias,
|
||||
result,
|
||||
null,
|
||||
null
|
||||
))
|
||||
{
|
||||
Connect_Failed_Count++;
|
||||
Is_Client_Connecting = false;
|
||||
LogUtil.LogD("ThreadLogin","Login Server Failed, Times: " + Connect_Failed_Count);
|
||||
LoginFailed(Connect_Failed_Count);
|
||||
// 连接失败,重新连接服务器
|
||||
ReconnectServer();
|
||||
return;
|
||||
}
|
||||
|
||||
// 登录成功
|
||||
Connect_Failed_Count = 0;
|
||||
//stateone.IpEndPoint = (IPEndPoint)socket.RemoteEndPoint;
|
||||
stateone.setClientType(ClientAlias);
|
||||
stateone.WorkSocket = socket;
|
||||
//stateone.WorkSocket.BeginReceive(stateone.BytesHead, stateone.AlreadyReceivedHead,
|
||||
//stateone.BytesHead.Length - stateone.AlreadyReceivedHead, SocketFlags.None,
|
||||
//new AsyncCallback(HeadReceiveCallback), stateone);
|
||||
|
||||
Thread receive = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ThreadReceiveBackground();
|
||||
}
|
||||
});
|
||||
receive.start();
|
||||
|
||||
|
||||
|
||||
// 发送一条验证消息
|
||||
byte[] bytesTemp = new byte[16];
|
||||
|
||||
//BitConverter.GetBytes(DateTime.Now.Ticks).CopyTo(bytesTemp, 0);
|
||||
SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Check_Secends, 0, KeyToken, bytesTemp));
|
||||
|
||||
|
||||
stateone.setHeartTime(new Date());
|
||||
Is_Client_Start = true;
|
||||
LoginSuccess();
|
||||
|
||||
LogUtil.LogD("ThreadLogin","Login Server Success, Times: " + Connect_Failed_Count);
|
||||
|
||||
Is_Client_Connecting = false;
|
||||
|
||||
ThreadSleep(1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ThreadReceiveBackground()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
OperateResult result = new OperateResult();
|
||||
boolWith2Bytes value = ReceiveAndCheckBytes(stateone.WorkSocket, result, null,null);
|
||||
|
||||
if (!value.Result)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 数据处理
|
||||
byte[] buffer1= new byte[4];
|
||||
buffer1[0] = value.Content[0];
|
||||
buffer1[1] = value.Content[1];
|
||||
buffer1[2] = value.Content[2];
|
||||
buffer1[3] = value.Content[3];
|
||||
|
||||
byte[] buffer2= new byte[4];
|
||||
buffer2[0] = value.Content[4];
|
||||
buffer2[1] = value.Content[5];
|
||||
buffer2[2] = value.Content[6];
|
||||
buffer2[3] = value.Content[7];
|
||||
|
||||
int protocol = Utilities.bytes2Int(buffer1);
|
||||
int customer = Utilities.bytes2Int(buffer2);
|
||||
|
||||
DataProcessingCenter(null,protocol,customer,value.Content2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private bool Is_reconnect_server = false;
|
||||
// private object lock_reconnect_server = new object();
|
||||
|
||||
|
||||
private void ReconnectServer()
|
||||
{
|
||||
// 是否连接服务器中,已经在连接的话,则不再连接
|
||||
if (Is_Client_Connecting) return;
|
||||
// 是否退出了系统,退出则不再重连
|
||||
if (IsQuie) return;
|
||||
|
||||
LogUtil.LogI("ReconnectServer","Prepare ReConnect Server.");
|
||||
|
||||
// 触发连接失败,重连系统前错误
|
||||
BeforReConnected();
|
||||
CloseSocket(stateone.WorkSocket);
|
||||
|
||||
Thread thread_login = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ThreadLogin();
|
||||
}
|
||||
});
|
||||
thread_login.start();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 通信出错后的处理
|
||||
/// </summary>
|
||||
/// <param name="receive"></param>
|
||||
/// <param name="ex"></param>
|
||||
void SocketReceiveException(AsyncStateOne receive, Exception ex)
|
||||
{
|
||||
if (ex.getMessage().contains(StringResources.SocketRemoteCloseException))
|
||||
{
|
||||
// 异常掉线
|
||||
ReconnectServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// MessageAlerts?.Invoke("数据接收出错:" + ex.Message);
|
||||
}
|
||||
|
||||
LogUtil.LogD("SocketReceiveException","Socket Excepiton Occured.");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 服务器端用于数据发送文本的方法
|
||||
/// </summary>
|
||||
/// <param name="customer">用户自定义的命令头</param>
|
||||
/// <param name="str">发送的文本</param>
|
||||
public void Send(NetHandle customer, String str)
|
||||
{
|
||||
if (Is_Client_Start)
|
||||
{
|
||||
SendBytes(stateone, NetSupport.CommandBytes(customer.get_CodeValue(), KeyToken, str));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 服务器端用于发送字节的方法
|
||||
/// </summary>
|
||||
/// <param name="customer">用户自定义的命令头</param>
|
||||
/// <param name="bytes">实际发送的数据</param>
|
||||
public void Send(NetHandle customer, byte[] bytes)
|
||||
{
|
||||
if (Is_Client_Start)
|
||||
{
|
||||
SendBytes(stateone, NetSupport.CommandBytes(customer.get_CodeValue(), KeyToken, bytes));
|
||||
}
|
||||
}
|
||||
|
||||
private void SendBytes(final AsyncStateOne stateone, final byte[] content)
|
||||
{
|
||||
Thread thread_login = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
stateone.WorkSocket.getOutputStream().write(content);
|
||||
} catch (Exception ex) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
thread_login.start();
|
||||
//SendBytesAsync(stateone, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端的数据处理中心
|
||||
/// </summary>
|
||||
/// <param name="receive"></param>
|
||||
/// <param name="protocol"></param>
|
||||
/// <param name="customer"></param>
|
||||
/// <param name="content"></param>
|
||||
void DataProcessingCenter(AsyncStateOne receive, int protocol, int customer, byte[] content)
|
||||
{
|
||||
if (protocol == HslCommunicationCode.Hsl_Protocol_Check_Secends)
|
||||
{
|
||||
//Date dt = new Date(BitConverter.ToInt64(content, 0));
|
||||
//ServerTime = new Date(BitConverter.ToInt64(content, 8));
|
||||
//DelayTime = (int)(new Date() - dt).TotalMilliseconds;
|
||||
stateone.setHeartTime(new Date());
|
||||
// MessageAlerts?.Invoke("心跳时间:" + DateTime.Now.ToString());
|
||||
}
|
||||
else if (protocol == HslCommunicationCode.Hsl_Protocol_Client_Quit)
|
||||
{
|
||||
// 申请了退出
|
||||
}
|
||||
else if (protocol == HslCommunicationCode.Hsl_Protocol_User_Bytes)
|
||||
{
|
||||
// 接收到字节数据
|
||||
AcceptByte(new NetHandle(customer), content);
|
||||
}
|
||||
else if (protocol == HslCommunicationCode.Hsl_Protocol_User_String)
|
||||
{
|
||||
// 接收到文本数据
|
||||
String str = Utilities.byte2String(content);
|
||||
AcceptString(new NetHandle(customer), str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Thread thread_heart_check = null;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳线程的方法
|
||||
/// </summary>
|
||||
private void ThreadHeartCheck()
|
||||
{
|
||||
|
||||
ThreadSleep(2000);
|
||||
while (true)
|
||||
{
|
||||
ThreadSleep(1000);
|
||||
|
||||
if (!IsQuie)
|
||||
{
|
||||
byte[] send = new byte[16];
|
||||
System.arraycopy(Utilities.long2Bytes(new Date().getTime()),0,send,0,8);
|
||||
SendBytes(stateone, NetSupport.CommandBytes(HslCommunicationCode.Hsl_Protocol_Check_Secends, 0, KeyToken, send));
|
||||
double timeSpan = (new Date().getTime() - stateone.getHeartTime().getTime())/1000;
|
||||
if (timeSpan > 1 * 8)//8次没有收到失去联系
|
||||
{
|
||||
LogUtil.LogD("ThreadHeartCheck","Heart Check Failed int "+timeSpan+" Seconds.");
|
||||
ReconnectServer();
|
||||
ThreadSleep(1000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.example.HslCommunication.Enthernet;
|
||||
|
||||
import com.example.HslCommunication.Core.Net.HslCommunicationCode;
|
||||
import com.example.HslCommunication.Core.Net.NetShareBase;
|
||||
import com.example.HslCommunication.Core.Net.ProgressReport;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWith2Bytes;
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
import com.example.HslCommunication.Core.Types.NetHandle;
|
||||
import com.example.HslCommunication.Core.Types.OperateResultBytes;
|
||||
import com.example.HslCommunication.Core.Types.OperateResultString;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithSocket;
|
||||
import com.example.HslCommunication.Resources.StringResources;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public final class NetSimplifyClient extends NetShareBase {
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 实例化一个客户端的对象,用于和服务器通信
|
||||
/// </summary>
|
||||
public NetSimplifyClient(String ipAddress, int port, UUID token)
|
||||
{
|
||||
m_ipAddress = ipAddress;
|
||||
m_port = port;
|
||||
KeyToken = token;
|
||||
}
|
||||
|
||||
private String m_ipAddress="127.0.0.1";
|
||||
private int m_port=10000;
|
||||
|
||||
/// <summary>
|
||||
/// 客户端向服务器进行请求,请求字符串数据
|
||||
/// </summary>
|
||||
/// <param name="customer">用户的指令头</param>
|
||||
/// <param name="send">发送数据</param>
|
||||
/// <param name="sendStatus">发送数据时的进度报告</param>
|
||||
/// <param name="receiveStatus">接收数据时的进度报告</param>
|
||||
/// <returns></returns>
|
||||
public OperateResultString ReadFromServer(
|
||||
NetHandle customer,
|
||||
String send,
|
||||
ProgressReport sendStatus,
|
||||
ProgressReport receiveStatus
|
||||
)
|
||||
{
|
||||
OperateResultString result = new OperateResultString();
|
||||
byte[] data = Utilities.string2Byte(send);
|
||||
OperateResultBytes temp = ReadFromServerBase(HslCommunicationCode.Hsl_Protocol_User_String, customer.get_CodeValue(), data, sendStatus, receiveStatus);
|
||||
result.IsSuccess = temp.IsSuccess;
|
||||
result.ErrorCode = temp.ErrorCode;
|
||||
result.Message = temp.Message;
|
||||
if (temp.IsSuccess)
|
||||
{
|
||||
result.Content = Utilities.byte2String(temp.Content);
|
||||
}
|
||||
temp = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 客户端向服务器进行请求,请求字节数据
|
||||
/// </summary>
|
||||
/// <param name="customer">用户的指令头</param>
|
||||
/// <param name="send"></param>
|
||||
/// <param name="sendStatus">发送数据的进度报告</param>
|
||||
/// <param name="receiveStatus">接收数据的进度报告</param>
|
||||
/// <returns></returns>
|
||||
public OperateResultBytes ReadFromServer(
|
||||
NetHandle customer,
|
||||
byte[] send,
|
||||
ProgressReport sendStatus,
|
||||
ProgressReport receiveStatus
|
||||
)
|
||||
{
|
||||
return ReadFromServerBase(HslCommunicationCode.Hsl_Protocol_User_Bytes, customer.get_CodeValue(), send, sendStatus, receiveStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 需要发送的底层数据
|
||||
/// </summary>
|
||||
/// <param name="headcode">数据的指令头</param>
|
||||
/// <param name="customer">用户的指令头</param>
|
||||
/// <param name="send">需要发送的底层数据</param>
|
||||
/// <param name="sendStatus">发送状态的进度报告,用于显示上传进度</param>
|
||||
/// <param name="receiveStatus">接收状态的进度报告,用于显示下载进度</param>
|
||||
/// <returns></returns>
|
||||
private OperateResultBytes ReadFromServerBase(
|
||||
int headcode,
|
||||
int customer,
|
||||
byte[] send,
|
||||
ProgressReport sendStatus,
|
||||
ProgressReport receiveStatus)
|
||||
{
|
||||
OperateResultBytes result = new OperateResultBytes();
|
||||
|
||||
// 创建并连接套接字
|
||||
Socket socket=null;
|
||||
boolWithSocket valueSocket=CreateSocketAndConnect(m_ipAddress, m_port,result);
|
||||
if(!valueSocket.Result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
socket = valueSocket.Socket;
|
||||
|
||||
// 发送并检查数据是否发送完成
|
||||
if (!SendBaseAndCheckReceive(socket, headcode, customer, send, result, sendStatus,null))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 接收头数据和内容数据
|
||||
|
||||
boolWith2Bytes value = ReceiveAndCheckBytes(socket, result, receiveStatus,null);
|
||||
|
||||
if (!value.Result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
CloseSocket(socket);
|
||||
result.Content = value.Content2;
|
||||
result.IsSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.example.HslCommunication.Log;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
* 一个扩展的日志工具,用来实现对记录日志的特殊处理,屏蔽操作
|
||||
*/
|
||||
|
||||
public class LogUtil {
|
||||
|
||||
public static final int VerBose = 1;
|
||||
|
||||
public static final int Debug = 2;
|
||||
|
||||
public static final int Info = 3;
|
||||
|
||||
public static final int Warn = 4;
|
||||
|
||||
public static final int Error = 5;
|
||||
|
||||
public static final int Nothing = 6;
|
||||
|
||||
public static int Level = VerBose;
|
||||
|
||||
/*
|
||||
记录零碎的日志
|
||||
*/
|
||||
public static void LogV(String tag, String msg) {
|
||||
if (Level <= VerBose) Log.v(tag, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
记录调试日志
|
||||
*/
|
||||
public static void LogD(String tag, String msg) {
|
||||
if (Level <= Debug) Log.d(tag, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
记录信息日志
|
||||
*/
|
||||
public static void LogI(String tag, String msg) {
|
||||
if (Level <= Info) Log.i(tag, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
记录警告日志
|
||||
*/
|
||||
public static void LogW(String tag, String msg) {
|
||||
if (Level <= Warn) Log.w(tag, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
记录一般错误日志
|
||||
*/
|
||||
public static void LogE(String tag, String msg) {
|
||||
if (Level <= Error) Log.e(tag, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
记录带信息异常的错误日志
|
||||
*/
|
||||
public static void LogE(String tag, String msg, Exception ex) {
|
||||
if (Level <= Error) Log.e(tag, msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.example.HslCommunication.Profinet;
|
||||
|
||||
import com.example.HslCommunication.Core.Net.NetBase;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/3.
|
||||
*/
|
||||
|
||||
public abstract class PlcNetBase extends NetBase {
|
||||
|
||||
|
||||
protected int m_PortRead = 1000;
|
||||
protected int m_PortReadBackup = -1;
|
||||
protected boolean m_IsPortNormal = true;
|
||||
protected int m_PortWrite = 1001;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取访问的端口号
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected int GetPort()
|
||||
{
|
||||
if (m_PortReadBackup <= 0) return m_PortRead;
|
||||
return m_IsPortNormal ? m_PortRead : m_PortReadBackup;
|
||||
}
|
||||
/// <summary>
|
||||
/// 更换端口号
|
||||
/// </summary>
|
||||
protected void ChangePort()
|
||||
{
|
||||
m_IsPortNormal = !m_IsPortNormal;
|
||||
}
|
||||
|
||||
|
||||
public void setPortRead(int value) {
|
||||
m_PortRead = value;
|
||||
}
|
||||
|
||||
|
||||
public int getPortRead()
|
||||
{
|
||||
return m_PortRead;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 控制字节长度,超出选择截断,不够补零
|
||||
/// </summary>
|
||||
/// <param name="bytes">字节数据</param>
|
||||
/// <param name="length">最终需要的目标长度</param>
|
||||
/// <returns>处理后的数据</returns>
|
||||
protected byte[] ManageBytesLength(byte[] bytes, int length)
|
||||
{
|
||||
if (bytes == null) return null;
|
||||
byte[] temp = new byte[length];
|
||||
if (length > bytes.length)
|
||||
{
|
||||
System.arraycopy(bytes, 0, temp, 0, bytes.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.arraycopy(bytes, 0, temp, 0, length);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.HslCommunication.Profinet;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/3.
|
||||
*/
|
||||
|
||||
public enum SiemensPLCS {
|
||||
S1200,
|
||||
S300,
|
||||
Smart200,
|
||||
}
|
||||
@@ -0,0 +1,780 @@
|
||||
package com.example.HslCommunication.Profinet;
|
||||
|
||||
import com.example.HslCommunication.Core.Net.NetSupport;
|
||||
import com.example.HslCommunication.Core.Types.OperateResult;
|
||||
import com.example.HslCommunication.Core.Types.OperateResultBytes;
|
||||
import com.example.HslCommunication.Core.Utilities.Utilities;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithBytes;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithSiemens;
|
||||
import com.example.HslCommunication.Core.Utilities.boolWithSocket;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/3.
|
||||
*/
|
||||
|
||||
public final class SiemensTcpNet extends PlcNetBase {
|
||||
|
||||
/// <summary>
|
||||
/// 实例化一个数据通信的对象,需要指定访问哪种Plc
|
||||
/// </summary>
|
||||
/// <param name="siemens"></param>
|
||||
public SiemensTcpNet(SiemensPLCS siemens)
|
||||
{
|
||||
m_PortRead = 102;
|
||||
m_PortWrite = 102;
|
||||
CurrentPlc = siemens;
|
||||
|
||||
switch (siemens)
|
||||
{
|
||||
case S1200: plcHead1[18] = 1; break;
|
||||
case S300: plcHead1[18] = 2; break;
|
||||
case Smart200:plcHead1[18] = 1; break;
|
||||
default: plcHead1[18] = 3; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 可以手动设置PLC类型,用来测试原本不支持的数据访问功能
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
public void SetPlcType(byte type)
|
||||
{
|
||||
plcHead1[18] = type;
|
||||
}
|
||||
|
||||
private String ipAddress="";
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public void setIpAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
|
||||
private boolWithBytes ReceiveBytesFromSocket(Socket socket)
|
||||
{
|
||||
boolWithBytes value =new boolWithBytes();
|
||||
try
|
||||
{
|
||||
// 先接收4个字节的数据
|
||||
byte[] head = NetSupport.ReadBytesFromSocket(socket, 4);
|
||||
int receive = head[2] * 256 + head[3];
|
||||
value.Content = new byte[receive];
|
||||
System.arraycopy(head,0,value.Content,0, 4);
|
||||
byte[] data = NetSupport.ReadBytesFromSocket(socket, receive - 4);
|
||||
System.arraycopy(data,0,value.Content,4,data.length);
|
||||
value.Result=true;
|
||||
return value;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean SendBytesToSocket(Socket socket, byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
OutputStream outputStream = socket.getOutputStream();
|
||||
outputStream.write(data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int CalculateAddressStarted(String address)
|
||||
{
|
||||
if (address.indexOf('.') < 0)
|
||||
{
|
||||
return Integer.parseInt(address) * 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] temp = address.split("\\.");
|
||||
return Integer.parseInt(temp[0]) * 8 + Integer.parseInt(temp[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析数据地址
|
||||
/// </summary>
|
||||
/// <param name="address">数据地址</param>
|
||||
/// <param name="type">类型</param>
|
||||
/// <param name="startAddress">其实地址</param>
|
||||
/// <param name="dbAddress">DB块地址</param>
|
||||
/// <param name="result">结果数据对象</param>
|
||||
/// <returns></returns>
|
||||
private boolWithSiemens AnalysisAddress(String address, OperateResult result)
|
||||
{
|
||||
boolWithSiemens value = new boolWithSiemens();
|
||||
try
|
||||
{
|
||||
value.dbAddress = 0;
|
||||
if (address.charAt(0) == 'I')
|
||||
{
|
||||
value.type = -127;
|
||||
value.startAddress = CalculateAddressStarted(address.substring(1));
|
||||
}
|
||||
else if (address.charAt(0) == 'Q')
|
||||
{
|
||||
value.type = -126;
|
||||
value.startAddress = CalculateAddressStarted(address.substring(1));
|
||||
}
|
||||
else if (address.charAt(0) == 'M')
|
||||
{
|
||||
value.type = -125;
|
||||
value.startAddress = CalculateAddressStarted(address.substring(1));
|
||||
}
|
||||
else if (address.charAt(0) == 'D' || address.substring(0, 2) == "DB")
|
||||
{
|
||||
value.type = -124;
|
||||
String[] adds = address.split("\\.");
|
||||
if (address.charAt(1) == 'B')
|
||||
{
|
||||
value.dbAddress = Short.parseShort(adds[0].substring(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
value.dbAddress = Short.parseShort(adds[0].substring(1));
|
||||
}
|
||||
|
||||
value.startAddress = CalculateAddressStarted(address.substring(address.indexOf('.') + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Message = "不支持的数据类型";
|
||||
value.type = 0;
|
||||
value.startAddress = 0;
|
||||
value.dbAddress = 0;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Message = ex.getMessage();
|
||||
return value;
|
||||
}
|
||||
|
||||
value.Result=true;
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean InitilizationConnect(Socket socket,OperateResult result)
|
||||
{
|
||||
// 发送初始化信息
|
||||
if(!SendBytesToSocket(socket,plcHead1))
|
||||
{
|
||||
result.Message = "初始化信息发送失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ReceiveBytesFromSocket(socket).Result)
|
||||
{
|
||||
result.Message = "初始化信息接收失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SendBytesToSocket(socket,plcHead2))
|
||||
{
|
||||
result.Message = "初始化信息发送失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ReceiveBytesFromSocket(socket).Result)
|
||||
{
|
||||
result.Message = "初始化信息接收失败";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位
|
||||
/// </summary>
|
||||
/// <param name="address">起始地址,格式为I100,M100,Q100,DB20.100</param>
|
||||
/// <param name="count">读取的数量,以字节为单位</param>
|
||||
/// <returns></returns>
|
||||
public OperateResultBytes ReadFromPLC(String address, short count)
|
||||
{
|
||||
return ReadFromPLC(new String[] { address }, new short[] { count });
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一次性从PLC获取所有的数据,按照先后顺序返回一个统一的Buffer,需要按照顺序处理,两个数组长度必须一致
|
||||
/// </summary>
|
||||
/// <param name="address">起始地址数组</param>
|
||||
/// <param name="count">数据长度数组</param>
|
||||
/// <returns></returns>
|
||||
public OperateResultBytes ReadFromPLC(String[] address, short[] count)
|
||||
{
|
||||
OperateResultBytes result = new OperateResultBytes();
|
||||
|
||||
if (address == null)
|
||||
{
|
||||
result.Message = "地址不能为空";
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if (count == null)
|
||||
{
|
||||
result.Message = "数量不能为空";
|
||||
return result;
|
||||
}
|
||||
if (address.length != count.length) {
|
||||
result.Message = "两个参数的个数不统一";
|
||||
return result;
|
||||
}
|
||||
|
||||
Socket socket;
|
||||
boolWithSocket value = CreateSocketAndConnect(ipAddress,getPortRead(), result);
|
||||
if (!value.Result)
|
||||
{
|
||||
ChangePort();
|
||||
return result;
|
||||
}
|
||||
|
||||
socket = value.Socket;
|
||||
if (!InitilizationConnect(socket, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// 分批次进行读取,计算总批次
|
||||
int times = address.length / 255;
|
||||
if (address.length % 255 > 0)
|
||||
{
|
||||
times++;
|
||||
}
|
||||
|
||||
// 缓存所有批次的结果
|
||||
ArrayList<byte[]> arrays_bytes = new ArrayList<byte[]>();
|
||||
|
||||
for (int jj = 0; jj < times; jj++)
|
||||
{
|
||||
// 计算本批次需要读取的数据
|
||||
int startIndex = jj * 255;
|
||||
int readCount = address.length - startIndex;
|
||||
if (readCount > 255)
|
||||
{
|
||||
readCount = 255;
|
||||
}
|
||||
|
||||
byte[] _PLCCommand = new byte[19 + readCount * 12];
|
||||
// 报文头
|
||||
_PLCCommand[0] = 0x03;
|
||||
_PLCCommand[1] = 0x00;
|
||||
// 长度
|
||||
_PLCCommand[2] = (byte)(_PLCCommand.length / 256);
|
||||
_PLCCommand[3] = (byte)(_PLCCommand.length % 256);
|
||||
// 固定
|
||||
_PLCCommand[4] = 0x02;
|
||||
_PLCCommand[5] = -16;
|
||||
_PLCCommand[6] = -128;
|
||||
_PLCCommand[7] = 0x32;
|
||||
// 命令:发
|
||||
_PLCCommand[8] = 0x01;
|
||||
// 标识序列号
|
||||
_PLCCommand[9] = 0x00;
|
||||
_PLCCommand[10] = 0x00;
|
||||
_PLCCommand[11] = 0x00;
|
||||
_PLCCommand[12] = 0x01;
|
||||
// 命令数据总长度
|
||||
_PLCCommand[13] = (byte)((_PLCCommand.length - 17) / 256);
|
||||
_PLCCommand[14] = (byte)((_PLCCommand.length - 17) % 256);
|
||||
|
||||
_PLCCommand[15] = 0x00;
|
||||
_PLCCommand[16] = 0x00;
|
||||
|
||||
// 命令起始符
|
||||
_PLCCommand[17] = 0x04;
|
||||
// 读取数据块个数
|
||||
_PLCCommand[18] = (byte)readCount;
|
||||
|
||||
int receiveCount = 0;
|
||||
for (int ii = 0; ii < readCount; ii++)
|
||||
{
|
||||
receiveCount += count[ii + 255 * jj];
|
||||
|
||||
boolWithSiemens siemens = AnalysisAddress(address[ii + 255 * jj], result);
|
||||
// 填充数据
|
||||
if (!siemens.Result)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 读取地址的前缀
|
||||
_PLCCommand[19 + ii * 12] = 0x12;
|
||||
_PLCCommand[20 + ii * 12] = 0x0A;
|
||||
_PLCCommand[21 + ii * 12] = 0x10;
|
||||
_PLCCommand[22 + ii * 12] = 0x02;
|
||||
// 访问数据的个数
|
||||
_PLCCommand[23 + ii * 12] = (byte)(count[ii + 255 * jj] / 256);
|
||||
_PLCCommand[24 + ii * 12] = (byte)(count[ii + 255 * jj] % 256);
|
||||
// DB块编号,如果访问的是DB块的话
|
||||
_PLCCommand[25 + ii * 12] = (byte)(siemens.dbAddress / 256);
|
||||
_PLCCommand[26 + ii * 12] = (byte)(siemens.dbAddress % 256);
|
||||
// 访问数据类型
|
||||
_PLCCommand[27 + ii * 12] = siemens.type;
|
||||
// 偏移位置
|
||||
_PLCCommand[28 + ii * 12] = (byte)(siemens.startAddress / 256 / 256);
|
||||
_PLCCommand[29 + ii * 12] = (byte)(siemens.startAddress / 256);
|
||||
_PLCCommand[30 + ii * 12] = (byte)(siemens.startAddress % 256);
|
||||
}
|
||||
|
||||
|
||||
if (!SendBytesToSocket(socket, _PLCCommand))
|
||||
{
|
||||
result.Message = "发送读取信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
boolWithBytes content=ReceiveBytesFromSocket(socket);
|
||||
if (!content.Result)
|
||||
{
|
||||
result.Message = "接收信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (content.Content.length != receiveCount + readCount * 4 + 21)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
result.Message = "数据长度校验失败";
|
||||
result.Content = content.Content;
|
||||
return result;
|
||||
}
|
||||
|
||||
// 分次读取成功
|
||||
byte[] buffer = new byte[receiveCount];
|
||||
int kk = 21;
|
||||
int ll = 0;
|
||||
for (int ii = 0; ii < readCount; ii++)
|
||||
{
|
||||
// 将数据挪回正确的地方
|
||||
System.arraycopy(content, kk + 4, buffer, ll, count[ii + 255 * jj]);
|
||||
kk += count[ii + 255 * jj] + 4;
|
||||
ll += count[ii + 255 * jj];
|
||||
}
|
||||
arrays_bytes.add(buffer);
|
||||
}
|
||||
|
||||
|
||||
if (arrays_bytes.size() == 1)
|
||||
{
|
||||
result.Content = arrays_bytes.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = 0;
|
||||
int offset = 0;
|
||||
|
||||
// 获取长度并生成缓冲数据
|
||||
|
||||
for(int ii=0;ii<arrays_bytes.size();ii++)
|
||||
{
|
||||
length += arrays_bytes.get(ii).length;
|
||||
}
|
||||
|
||||
result.Content = new byte[length];
|
||||
|
||||
// 复制数据操作
|
||||
for(int ii=0;ii<arrays_bytes.size();ii++)
|
||||
{
|
||||
System.arraycopy(arrays_bytes.get(ii),0,result.Content,offset,arrays_bytes.get(ii).length);
|
||||
offset+=arrays_bytes.get(ii).length;
|
||||
}
|
||||
arrays_bytes.clear();
|
||||
}
|
||||
result.IsSuccess = true;
|
||||
CloseSocket(socket);
|
||||
//所有的数据接收完成,进行返回
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数据写入到PLC数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位
|
||||
/// </summary>
|
||||
/// <param name="address">起始地址,格式为I100,M100,Q100,DB20.100</param>
|
||||
/// <param name="data">写入的数据,长度根据data的长度来指示</param>
|
||||
/// <returns></returns>
|
||||
public OperateResult WriteIntoPLC(String address, byte[] data)
|
||||
{
|
||||
OperateResult result = new OperateResult();
|
||||
|
||||
|
||||
Socket socket;
|
||||
boolWithSocket value = CreateSocketAndConnect(ipAddress,getPortRead(), result);
|
||||
if (!value.Result)
|
||||
{
|
||||
ChangePort();
|
||||
return result;
|
||||
}
|
||||
|
||||
socket = value.Socket;
|
||||
if (!InitilizationConnect(socket, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
if (data == null) data = new byte[0];
|
||||
|
||||
boolWithSiemens siemens = AnalysisAddress(address, result);
|
||||
// 填充数据
|
||||
if (!siemens.Result)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
byte[] _PLCCommand = new byte[35 + data.length];
|
||||
_PLCCommand[0] = 0x03;
|
||||
_PLCCommand[1] = 0x00;
|
||||
// 长度
|
||||
_PLCCommand[2] = (byte)((35 + data.length) / 256);
|
||||
_PLCCommand[3] = (byte)((35 + data.length) % 256);
|
||||
// 固定
|
||||
_PLCCommand[4] = 0x02;
|
||||
_PLCCommand[5] = -16;
|
||||
_PLCCommand[6] = -128;
|
||||
_PLCCommand[7] = 0x32;
|
||||
// 命令 发
|
||||
_PLCCommand[8] = 0x01;
|
||||
// 标识序列号
|
||||
_PLCCommand[9] = 0x00;
|
||||
_PLCCommand[10] = 0x00;
|
||||
_PLCCommand[11] = 0x00;
|
||||
_PLCCommand[12] = 0x01;
|
||||
// 固定
|
||||
_PLCCommand[13] = 0x00;
|
||||
_PLCCommand[14] = 0x0E;
|
||||
// 写入长度+4
|
||||
_PLCCommand[15] = (byte)((4 + data.length) / 256);
|
||||
_PLCCommand[16] = (byte)((4 + data.length) % 256);
|
||||
// 命令起始符
|
||||
_PLCCommand[17] = 0x05;
|
||||
// 写入数据块个数
|
||||
_PLCCommand[18] = 0x01;
|
||||
// 固定,返回数据长度
|
||||
_PLCCommand[19] = 0x12;
|
||||
_PLCCommand[20] = 0x0A;
|
||||
_PLCCommand[21] = 0x10;
|
||||
// 写入方式,1是按位,2是按字
|
||||
_PLCCommand[22] = 0x02;
|
||||
// 写入数据的个数
|
||||
_PLCCommand[23] = (byte)(data.length / 256);
|
||||
_PLCCommand[24] = (byte)(data.length % 256);
|
||||
// DB块编号,如果访问的是DB块的话
|
||||
_PLCCommand[25] = (byte)(siemens.dbAddress / 256);
|
||||
_PLCCommand[26] = (byte)(siemens.dbAddress % 256);
|
||||
// 写入数据的类型
|
||||
_PLCCommand[27] = siemens.type;
|
||||
// 偏移位置
|
||||
_PLCCommand[28] = (byte)(siemens.startAddress / 256 / 256);;
|
||||
_PLCCommand[29] = (byte)(siemens.startAddress / 256);
|
||||
_PLCCommand[30] = (byte)(siemens.startAddress % 256);
|
||||
// 按字写入
|
||||
_PLCCommand[31] = 0x00;
|
||||
_PLCCommand[32] = 0x04;
|
||||
// 按位计算的长度
|
||||
_PLCCommand[33] = (byte)(data.length * 8 / 256);
|
||||
_PLCCommand[34] = (byte)(data.length * 8 % 256);
|
||||
|
||||
System.arraycopy(data,0,_PLCCommand,35,data.length);
|
||||
|
||||
if(!SendBytesToSocket(socket,_PLCCommand))
|
||||
{
|
||||
result.Message = "发送写入信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
boolWithBytes value2=ReceiveBytesFromSocket(socket);
|
||||
if (!value2.Result)
|
||||
{
|
||||
result.Message = "接收信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (value2.Content[value2.Content.length - 1] != 0xFF)
|
||||
{
|
||||
// 写入异常
|
||||
CloseSocket(socket);
|
||||
result.Message = "写入数据异常";
|
||||
return result;
|
||||
}
|
||||
|
||||
CloseSocket(socket);
|
||||
result.IsSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入PLC的一个位,例如"M100.6","I100.7","Q100.0","DB20.100.0",如果只写了"M100"默认为"M100.0
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public OperateResult WriteIntoPLC(String address, boolean data)
|
||||
{
|
||||
OperateResult result = new OperateResult();
|
||||
|
||||
Socket socket;
|
||||
boolWithSocket value = CreateSocketAndConnect(getIpAddress(),m_PortWrite, result);
|
||||
if (!value.Result)
|
||||
{
|
||||
ChangePort();
|
||||
return result;
|
||||
}
|
||||
|
||||
socket = value.Socket;
|
||||
if (!InitilizationConnect(socket, result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
byte[] buffer = new byte[1];
|
||||
buffer[0] = data ? (byte)0x01 : (byte)0x00;
|
||||
|
||||
boolWithSiemens siemens = AnalysisAddress(address, result);
|
||||
// 填充数据
|
||||
if (!siemens.Result)
|
||||
{
|
||||
CloseSocket(socket);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
byte[] _PLCCommand = new byte[35 + buffer.length];
|
||||
_PLCCommand[0] = 0x03;
|
||||
_PLCCommand[1] = 0x00;
|
||||
// 长度
|
||||
_PLCCommand[2] = (byte)((35 + buffer.length) / 256);
|
||||
_PLCCommand[3] = (byte)((35 + buffer.length) % 256);
|
||||
// 固定
|
||||
_PLCCommand[4] = 0x02;
|
||||
_PLCCommand[5] = -16;
|
||||
_PLCCommand[6] = -128;
|
||||
_PLCCommand[7] = 0x32;
|
||||
// 命令 发
|
||||
_PLCCommand[8] = 0x01;
|
||||
// 标识序列号
|
||||
_PLCCommand[9] = 0x00;
|
||||
_PLCCommand[10] = 0x00;
|
||||
_PLCCommand[11] = 0x00;
|
||||
_PLCCommand[12] = 0x01;
|
||||
// 固定
|
||||
_PLCCommand[13] = 0x00;
|
||||
_PLCCommand[14] = 0x0E;
|
||||
// 写入长度+4
|
||||
_PLCCommand[15] = (byte)((4 + buffer.length) / 256);
|
||||
_PLCCommand[16] = (byte)((4 + buffer.length) % 256);
|
||||
// 命令起始符
|
||||
_PLCCommand[17] = 0x05;
|
||||
// 写入数据块个数
|
||||
_PLCCommand[18] = 0x01;
|
||||
_PLCCommand[19] = 0x12;
|
||||
_PLCCommand[20] = 0x0A;
|
||||
_PLCCommand[21] = 0x10;
|
||||
// 写入方式,1是按位,2是按字
|
||||
_PLCCommand[22] = 0x01;
|
||||
// 写入数据的个数
|
||||
_PLCCommand[23] = (byte)(buffer.length / 256);
|
||||
_PLCCommand[24] = (byte)(buffer.length % 256);
|
||||
// DB块编号,如果访问的是DB块的话
|
||||
_PLCCommand[25] = (byte)(siemens.dbAddress / 256);
|
||||
_PLCCommand[26] = (byte)(siemens.dbAddress % 256);
|
||||
// 写入数据的类型
|
||||
_PLCCommand[27] = siemens.type;
|
||||
// 偏移位置
|
||||
_PLCCommand[28] = (byte)(siemens.startAddress / 256 / 256);
|
||||
_PLCCommand[29] = (byte)(siemens.startAddress / 256);
|
||||
_PLCCommand[30] = (byte)(siemens.startAddress % 256);
|
||||
// 按位写入
|
||||
_PLCCommand[31] = 0x00;
|
||||
_PLCCommand[32] = 0x03;
|
||||
// 按位计算的长度
|
||||
_PLCCommand[33] = (byte)(buffer.length / 256);
|
||||
_PLCCommand[34] = (byte)(buffer.length % 256);
|
||||
|
||||
System.arraycopy(buffer,0,_PLCCommand,35,buffer.length);
|
||||
|
||||
if(!SendBytesToSocket(socket,_PLCCommand))
|
||||
{
|
||||
result.Message = "发送写入信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
boolWithBytes value2=ReceiveBytesFromSocket(socket);
|
||||
if (!value2.Result)
|
||||
{
|
||||
result.Message = "接收信息失败";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (value2.Content[value2.Content.length - 1] != 0xFF)
|
||||
{
|
||||
// 写入异常
|
||||
CloseSocket(socket);
|
||||
result.Message = "写入数据异常";
|
||||
return result;
|
||||
}
|
||||
|
||||
CloseSocket(socket);
|
||||
result.IsSuccess = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从返回的西门子数组中获取short数组数据,已经内置高地位转换
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns></returns>
|
||||
public short[] GetArrayFromBytes(byte[] bytes)
|
||||
{
|
||||
short[] temp = new short[bytes.length / 2];
|
||||
for (int i = 0; i < temp.length; i++)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
buffer[0] = bytes[i * 2 + 1];
|
||||
buffer[1] = bytes[i * 2];
|
||||
temp[i] = Utilities.byte2Short(buffer, 0);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从返回的西门子数组中获取int数组数据,已经内置高地位转换
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns></returns>
|
||||
public int[] GetIntArrayFromBytes(byte[] bytes)
|
||||
{
|
||||
int[] temp = new int[bytes.length / 4];
|
||||
for (int i = 0; i < temp.length; i++)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0] = bytes[i * 4 + 0];
|
||||
buffer[1] = bytes[i * 4 + 1];
|
||||
buffer[2] = bytes[i * 4 + 2];
|
||||
buffer[3] = bytes[i * 4 + 3];
|
||||
temp[i] = Utilities.bytes2Int(buffer);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据索引位转换获取short数据
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public short GetShortFromBytes(byte[] content, int index)
|
||||
{
|
||||
byte[] buffer = new byte[2];
|
||||
buffer[0] = content[index + 0];
|
||||
buffer[1] = content[index + 1];
|
||||
return Utilities.byte2Short(buffer,0);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据索引位转换获取int数据
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public int GetIntFromBytes(byte[] content, int index)
|
||||
{
|
||||
byte[] buffer = new byte[4];
|
||||
buffer[0] = content[index + 0];
|
||||
buffer[1] = content[index + 1];
|
||||
buffer[2] = content[index + 2];
|
||||
buffer[3] = content[index + 3];
|
||||
return Utilities.bytes2Int(buffer);
|
||||
}
|
||||
|
||||
private byte[] plcHead1 =
|
||||
{
|
||||
0x03, // 报文头
|
||||
0x00,
|
||||
0x00, // 数据长度
|
||||
0x16,
|
||||
0x11,
|
||||
-32,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x00,
|
||||
-63,
|
||||
0x02,
|
||||
0x10,
|
||||
0x00,
|
||||
-62,
|
||||
0x02,
|
||||
0x03,
|
||||
0x01, // 指示cpu
|
||||
-64,
|
||||
0x01,
|
||||
0x0A
|
||||
};
|
||||
private byte[] plcHead2 =
|
||||
{
|
||||
0x03,
|
||||
0x00,
|
||||
0x00,
|
||||
0x19,
|
||||
0x02,
|
||||
-16,
|
||||
-128,
|
||||
0x32,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
-52,
|
||||
-63,
|
||||
0x00,
|
||||
0x08,
|
||||
0x00,
|
||||
0x00,
|
||||
-16,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x00,
|
||||
0x01,
|
||||
0x03,
|
||||
-64
|
||||
};
|
||||
|
||||
private SiemensPLCS CurrentPlc = SiemensPLCS.S1200;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.example.HslCommunication.Resources;
|
||||
|
||||
/**
|
||||
* Created by DATHLIN on 2017/11/2.
|
||||
*/
|
||||
|
||||
public class StringResources {
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* 一般的错误信息
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
|
||||
public static final String ConnectedFailed = "连接失败";
|
||||
public static final String UnknownError = "未知错误";
|
||||
public static final String ErrorCode = "错误代号";
|
||||
public static final String TextDescription = "文本描述";
|
||||
public static final String ExceptionMessage = "错误信息:";
|
||||
public static final String ExceptionStackTrace = "错误堆栈:";
|
||||
public static final String ExceptopnTargetSite = "错误方法:";
|
||||
public static final String ExceprionCustomer = "用户自定义方法出错:";
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* 系统相关的错误信息
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
public static final String SystemInstallOperater = "安装新系统:IP为";
|
||||
public static final String SystemUpdateOperater = "更新新系统:IP为";
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* 套接字相关的信息描述
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
public static final String SocketIOException = "套接字传送数据异常:";
|
||||
public static final String SocketSendException = "同步数据发送异常:";
|
||||
public static final String SocketHeadReceiveException = "指令头接收异常:";
|
||||
public static final String SocketContentReceiveException = "内容数据接收异常:";
|
||||
public static final String SocketContentRemoteReceiveException = "对方内容数据接收异常:";
|
||||
public static final String SocketAcceptCallbackException = "异步接受传入的连接尝试";
|
||||
public static final String SocketReAcceptCallbackException = "重新异步接受传入的连接尝试";
|
||||
public static final String SocketSendAsyncException = "异步数据发送出错:";
|
||||
public static final String SocketEndSendException = "异步数据结束挂起发送出错";
|
||||
public static final String SocketReceiveException = "异步数据发送出错:";
|
||||
public static final String SocketEndReceiveException = "异步数据结束接收指令头出错";
|
||||
public static final String SocketRemoteCloseException = "远程主机强迫关闭了一个现有的连接";
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* 文件相关的信息
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
|
||||
public static final String FileDownloadSuccess = "文件下载成功";
|
||||
public static final String FileDownloadFailed = "文件下载异常";
|
||||
public static final String FileUploadFailed = "文件上传异常";
|
||||
public static final String FileUploadSuccess = "文件上传成功";
|
||||
public static final String FileDeleteFailed = "文件删除异常";
|
||||
public static final String FileDeleteSuccess = "文件删除成功";
|
||||
public static final String FileReceiveFailed = "确认文件接收异常";
|
||||
public static final String FileNotExist = "文件不存在";
|
||||
public static final String FileSaveFailed = "文件存储失败";
|
||||
public static final String FileLoadFailed = "文件加载失败";
|
||||
public static final String FileSendClientFailed = "文件发送的时候发生了异常";
|
||||
public static final String FileWriteToNetFailed = "文件写入网络异常";
|
||||
public static final String FileReadFromNetFailed = "从网络读取文件异常";
|
||||
|
||||
/***********************************************************************************
|
||||
*
|
||||
* 服务器的引擎相关数据
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
public static final String TokenCheckFailed = "接收验证令牌不一致";
|
||||
public static final String TokenCheckTimeout = "接收验证超时:";
|
||||
public static final String NetClientAliasFailed = "客户端的别名接收失败:";
|
||||
public static final String NetEngineStart = "启动引擎";
|
||||
public static final String NetEngineClose = "关闭引擎";
|
||||
public static final String NetClientOnline = "上线";
|
||||
public static final String NetClientOffline = "下线";
|
||||
public static final String NetClientBreak = "异常掉线";
|
||||
public static final String NetClientFull = "服务器承载上限,收到超出的请求连接。";
|
||||
public static final String NetClientLoginFailed = "客户端登录中错误:";
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.UserSoftwareAndroidTemplate.CommonHeadCode;
|
||||
|
||||
import com.example.HslCommunication.Core.Types.NetHandle;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/5.
|
||||
*/
|
||||
|
||||
public class SimplifyHeadCode {
|
||||
|
||||
|
||||
public static NetHandle 维护检查 = new NetHandle(1, 1, 1);
|
||||
public static NetHandle 更新检查 = new NetHandle(1, 1, 2);
|
||||
public static NetHandle 参数下载 = new NetHandle(1, 1, 3);
|
||||
public static NetHandle 账户检查 = new NetHandle(1, 1, 4);
|
||||
public static NetHandle 密码修改 = new NetHandle(1, 1, 5);
|
||||
public static NetHandle 更细账户 = new NetHandle(1, 1, 6);
|
||||
public static NetHandle 获取账户 = new NetHandle(1, 1, 7);
|
||||
public static NetHandle 更新公告 = new NetHandle(1, 1, 8);
|
||||
public static NetHandle 注册账号 = new NetHandle(1, 1, 9);
|
||||
public static NetHandle 更新版本 = new NetHandle(1, 1, 10);
|
||||
public static NetHandle 请求文件 = new NetHandle(1, 1, 11);
|
||||
public static NetHandle 意见反馈 = new NetHandle(1, 1, 12);
|
||||
public static NetHandle 群发消息 = new NetHandle(1, 1, 13);
|
||||
public static NetHandle 异常消息 = new NetHandle(1, 1, 14);
|
||||
public static NetHandle 性能计数 = new NetHandle(1, 1, 15);
|
||||
public static NetHandle 上传头像MD5 = new NetHandle(1, 1, 16);
|
||||
public static NetHandle 请求分厂 = new NetHandle(1, 1, 17);
|
||||
public static NetHandle 上传分厂 = new NetHandle(1, 1, 18);
|
||||
public static NetHandle 请求信任客户端 = new NetHandle(1, 1, 19);
|
||||
public static NetHandle 上传信任客户端 = new NetHandle(1, 1, 20);
|
||||
public static NetHandle 请求一般配置 = new NetHandle(1, 1, 21);
|
||||
public static NetHandle 上传一般配置 = new NetHandle(1, 1, 22);
|
||||
public static NetHandle 请求角色配置 = new NetHandle(1, 1, 23);
|
||||
public static NetHandle 上传角色配置 = new NetHandle(1, 1, 24);
|
||||
public static NetHandle 检查角色权限 = new NetHandle(1, 1, 25);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static NetHandle 网络日志查看 = new NetHandle(1, 2, 1);//1.2.开头的是日志请求和清空
|
||||
public static NetHandle 网络日志清空 = new NetHandle(1, 2, 2);
|
||||
public static NetHandle 同步日志查看 = new NetHandle(1, 2, 3);
|
||||
public static NetHandle 同步日志清空 = new NetHandle(1, 2, 4);
|
||||
public static NetHandle 更新日志查看 = new NetHandle(1, 2, 5);
|
||||
public static NetHandle 更新日志清空 = new NetHandle(1, 2, 6);
|
||||
public static NetHandle 运行日志查看 = new NetHandle(1, 2, 7);
|
||||
public static NetHandle 运行日志清空 = new NetHandle(1, 2, 8);
|
||||
public static NetHandle 文件日志查看 = new NetHandle(1, 2, 9);
|
||||
public static NetHandle 文件日志清空 = new NetHandle(1, 2, 10);
|
||||
public static NetHandle 反馈日志查看 = new NetHandle(1, 2, 11);
|
||||
public static NetHandle 反馈日志清空 = new NetHandle(1, 2, 12);
|
||||
public static NetHandle UDP日志查看 = new NetHandle(1, 2, 13);
|
||||
public static NetHandle UDP日志清空 = new NetHandle(1, 2, 14);
|
||||
public static NetHandle 客户端日志查看 = new NetHandle(1, 2, 15);
|
||||
public static NetHandle 客户端日志清空 = new NetHandle(1, 2, 16);
|
||||
public static NetHandle 头像日志查看 = new NetHandle(1, 2, 17);
|
||||
public static NetHandle 头像日志清空 = new NetHandle(1, 2, 18);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.example.UserSoftwareAndroidTemplate.LoginSupport;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.HslCommunication.BasicFramework.SystemVersion;
|
||||
import com.example.HslCommunication.Core.Types.NetHandle;
|
||||
import com.example.HslCommunication.Core.Types.OperateResultString;
|
||||
import com.example.UserSoftwareAndroidTemplate.CommonHeadCode.SimplifyHeadCode;
|
||||
import com.example.UserSoftwareAndroidTemplate.MainActivity;
|
||||
import com.example.UserSoftwareAndroidTemplate.R;
|
||||
import com.example.UserSoftwareAndroidTemplate.UserClient;
|
||||
|
||||
|
||||
public class SplashActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_splash);
|
||||
|
||||
TextView mVersionNameText = (TextView) findViewById(R.id.TextVersionInfo);
|
||||
mVersionNameText.setText("Version: " + UserClient.CurrentVersion.toString());
|
||||
|
||||
new AsyncTask<Void, Void, Integer>() {
|
||||
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... voids) {
|
||||
int result;
|
||||
long startTime = System.currentTimeMillis();
|
||||
result = loadingCache();
|
||||
long loadingTime = System.currentTimeMillis() - startTime;
|
||||
if (loadingTime < SHOW_TIME_MIN) {
|
||||
try {
|
||||
Thread.sleep(SHOW_TIME_MIN - loadingTime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
if (result > 0) {
|
||||
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
|
||||
//intent.setClassName(SplashActivity.this, getString(R.string.));
|
||||
startActivity(intent);
|
||||
finish();
|
||||
//两个参数分别表示进入的动画,退出的动画
|
||||
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
}.execute(new Void[]{});
|
||||
|
||||
}
|
||||
|
||||
private static final int SHOW_TIME_MIN = 3000;
|
||||
private static final int FAILURE = 0; // 失败
|
||||
private static final int SUCCESS = 1; // 成功
|
||||
private static final int OFFLINE = 2; // 如果支持离线阅读,进入离线模式
|
||||
|
||||
|
||||
private Handler handler=new Handler(){
|
||||
/**重写handleMessage方法*/
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.arg1 == 1) {
|
||||
Toast.makeText(SplashActivity.this, msg.obj.toString(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private void MessageShow(String message)
|
||||
{
|
||||
Message msg = new Message();
|
||||
msg.arg1=1;
|
||||
msg.obj = message;
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
private int loadingCache() {
|
||||
|
||||
// 第一步请求维护状态
|
||||
OperateResultString result=UserClient.Client.ReadFromServer(SimplifyHeadCode.维护检查,"",null,null);
|
||||
if(!result.IsSuccess){
|
||||
MessageShow(result.ToMessageShowString());
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if(!result.Content.equals("1")) {
|
||||
MessageShow(result.Content.substring(1));
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// 第二步检查账户
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 第三步检查版本
|
||||
result=UserClient.Client.ReadFromServer(SimplifyHeadCode.维护检查,"",null,null);
|
||||
if(!result.IsSuccess){
|
||||
MessageShow(result.ToMessageShowString());
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
SystemVersion sv=new SystemVersion(result.Content);
|
||||
if(!UserClient.CurrentVersion.IsSameVersion(sv)) return FAILURE;
|
||||
|
||||
|
||||
// 下载服务器数据
|
||||
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.example.UserSoftwareAndroidTemplate;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.HslCommunication.Core.Types.NetHandle;
|
||||
import com.example.HslCommunication.Core.Types.OperateResultString;
|
||||
import com.example.HslCommunication.Enthernet.NetSimplifyClient;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
public MainActivity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private Handler handler=new Handler(){
|
||||
/**重写handleMessage方法*/
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.arg1 == 1) {
|
||||
|
||||
// 说明是一个网络的请求访问
|
||||
OperateResultString result = (OperateResultString) msg.obj;
|
||||
if (result.IsSuccess) {
|
||||
TextView textView = (TextView) findViewById(R.id.textViewMain);
|
||||
textView.setText(result.Content);
|
||||
} else {
|
||||
Toast.makeText(MainActivity.this, result.ToMessageShowString(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 网络操作相关的子线程
|
||||
*/
|
||||
Runnable networkTask = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// 在这里进行网络请求相关操作
|
||||
Message msg = new Message();
|
||||
OperateResultString result = UserClient.Client.ReadFromServer(new NetHandle(1,2, 15),"",null,null);
|
||||
msg.arg1=1;
|
||||
msg.obj = result;
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
Button button1 = (Button) findViewById(R.id.button);
|
||||
button1.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
new Thread(networkTask).start();
|
||||
}});
|
||||
|
||||
TextView textView = (TextView) findViewById(R.id.textViewMain);
|
||||
textView.setMovementMethod(new ScrollingMovementMethod());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.UserSoftwareAndroidTemplate;
|
||||
|
||||
import com.example.HslCommunication.BasicFramework.SystemVersion;
|
||||
import com.example.HslCommunication.Enthernet.NetSimplifyClient;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by hsl20 on 2017/11/4.
|
||||
*/
|
||||
|
||||
public class UserClient {
|
||||
|
||||
|
||||
public static SystemVersion CurrentVersion= new SystemVersion("1.0.0.171026");
|
||||
|
||||
|
||||
|
||||
public static String ServerIp="117.48.203.204";
|
||||
public static int PortSecondary=14568;
|
||||
public static UUID Token=UUID.fromString("1275BB9A-14B2-4A96-9673-B0AF0463D474");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static NetSimplifyClient Client=new NetSimplifyClient(ServerIp,PortSecondary,Token);
|
||||
|
||||
}
|
||||
8
AndroidTemplate/app/src/main/res/anim/fade_in.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha
|
||||
android:fromAlpha="0"
|
||||
android:toAlpha="1"
|
||||
android:duration="500" />
|
||||
</set>
|
||||
8
AndroidTemplate/app/src/main/res/anim/fade_out.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha
|
||||
android:fromAlpha="1"
|
||||
android:toAlpha="0"
|
||||
android:duration="500" />
|
||||
</set>
|
||||
@@ -0,0 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
||||
26
AndroidTemplate/app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.example.UserSoftwareAndroidTemplate.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewMain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:scrollbars="vertical"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Button" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
77
AndroidTemplate/app/src/main/res/layout/activity_splash.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="#ffffff"
|
||||
|
||||
tools:context="com.example.UserSoftwareAndroidTemplate.LoginSupport.SplashActivity">
|
||||
|
||||
<TextView android:id="@+id/copy_right"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dip"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:text="by Richard.Hu 出品"
|
||||
android:textSize="11sp"/>
|
||||
<RelativeLayout android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_centerInParent="true">
|
||||
<RelativeLayout android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
<ImageView android:id="@+id/jay_studio_icon"
|
||||
android:layout_width="110dip"
|
||||
android:layout_height="130dip"
|
||||
/>
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/jay_studio_icon"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
<LinearLayout android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
<TextView android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dip"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="24sp"/>
|
||||
<TextView android:id="@+id/version_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="bottom"
|
||||
android:paddingBottom="6dip"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
<View android:layout_width="fill_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_marginLeft="20dip"
|
||||
android:layout_marginRight="20dip"
|
||||
android:background="#dddddd"/>
|
||||
<TextView android:layout_width="wrap_content"
|
||||
android:id="@+id/TextVersionInfo"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:padding="6dip"
|
||||
android:text="Verion:"
|
||||
android:textSize="13sp"/>
|
||||
<ProgressBar android:id="@+id/refresh_list_footer_progressbar"
|
||||
android:layout_width="24dip"
|
||||
android:layout_height="24dip"
|
||||
|
||||
android:layout_gravity="center">
|
||||
</ProgressBar>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
AndroidTemplate/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
BIN
AndroidTemplate/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
BIN
AndroidTemplate/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
BIN
AndroidTemplate/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
BIN
AndroidTemplate/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 15 KiB |
12
AndroidTemplate/app/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<resources>
|
||||
|
||||
<!-- Declare custom theme attributes that allow changing which styles are
|
||||
used for button bars depending on the API level.
|
||||
?android:attr/buttonBarStyle is new as of API 11 so this is
|
||||
necessary to support previous API levels. -->
|
||||
<declare-styleable name="ButtonBarContainerTheme">
|
||||
<attr name="metaButtonBarStyle" format="reference" />
|
||||
<attr name="metaButtonBarButtonStyle" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
8
AndroidTemplate/app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
|
||||
<color name="black_overlay">#66000000</color>
|
||||
</resources>
|
||||
3
AndroidTemplate/app/src/main/res/values/dimens.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
8
AndroidTemplate/app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<resources>
|
||||
<string name="app_name">软件系统安卓端模版</string>
|
||||
<string name="title_activity_splash">SplashActivity</string>
|
||||
|
||||
<string name="title_activity_loading">LoadingActivity</string>
|
||||
<string name="dummy_button">Dummy Button</string>
|
||||
<string name="dummy_content">DUMMY\nCONTENT</string>
|
||||
</resources>
|
||||
32
AndroidTemplate/app/src/main/res/values/styles.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<style name="FullscreenTheme" parent="AppTheme">
|
||||
<item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
|
||||
<item name="android:windowActionBarOverlay">true</item>
|
||||
<item name="android:windowBackground">@null</item>
|
||||
<item name="metaButtonBarStyle">?android:attr/buttonBarStyle</item>
|
||||
<item name="metaButtonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="FullscreenActionBarStyle" parent="Widget.AppCompat.ActionBar">
|
||||
<item name="android:background">@color/black_overlay</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.example.UserSoftwareAndroidTemplate;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
27
AndroidTemplate/build.gradle
Normal file
@@ -0,0 +1,27 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
17
AndroidTemplate/gradle.properties
Normal file
@@ -0,0 +1,17 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx512m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
BIN
AndroidTemplate/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
AndroidTemplate/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Sun Oct 29 15:00:29 CST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-4.3-rc-4-all.zip
|
||||
160
AndroidTemplate/gradlew
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# 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
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# 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
|
||||
|
||||
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" ] ; 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
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
90
AndroidTemplate/gradlew.bat
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
@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
|
||||
|
||||
@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=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@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 Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_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=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
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
|
||||
1
AndroidTemplate/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
include ':app'
|
||||
38
HslCommunicationNetTestTool/Form1.Designer.cs
generated
@@ -47,7 +47,11 @@
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.panel1.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// userButton1
|
||||
@@ -88,7 +92,7 @@
|
||||
treeNode1.Text = "NetSimplifyClient";
|
||||
this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
|
||||
treeNode1});
|
||||
this.treeView1.Size = new System.Drawing.Size(254, 614);
|
||||
this.treeView1.Size = new System.Drawing.Size(254, 601);
|
||||
this.treeView1.TabIndex = 2;
|
||||
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
|
||||
//
|
||||
@@ -113,7 +117,7 @@
|
||||
this.panel1.Controls.Add(this.label1);
|
||||
this.panel1.Location = new System.Drawing.Point(280, 56);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(779, 613);
|
||||
this.panel1.Size = new System.Drawing.Size(779, 601);
|
||||
this.panel1.TabIndex = 3;
|
||||
//
|
||||
// userButton4
|
||||
@@ -175,7 +179,7 @@
|
||||
this.textBox3.Multiline = true;
|
||||
this.textBox3.Name = "textBox3";
|
||||
this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.textBox3.Size = new System.Drawing.Size(702, 327);
|
||||
this.textBox3.Size = new System.Drawing.Size(702, 315);
|
||||
this.textBox3.TabIndex = 7;
|
||||
//
|
||||
// label4
|
||||
@@ -254,11 +258,34 @@
|
||||
this.label7.TabIndex = 4;
|
||||
this.label7.Text = "选中连接:";
|
||||
//
|
||||
// statusStrip1
|
||||
//
|
||||
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.toolStripStatusLabel1,
|
||||
this.toolStripStatusLabel2});
|
||||
this.statusStrip1.Location = new System.Drawing.Point(0, 661);
|
||||
this.statusStrip1.Name = "statusStrip1";
|
||||
this.statusStrip1.Size = new System.Drawing.Size(1072, 22);
|
||||
this.statusStrip1.TabIndex = 5;
|
||||
this.statusStrip1.Text = "statusStrip1";
|
||||
//
|
||||
// toolStripStatusLabel1
|
||||
//
|
||||
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
|
||||
this.toolStripStatusLabel1.Size = new System.Drawing.Size(92, 17);
|
||||
this.toolStripStatusLabel1.Text = "十六进制命令:";
|
||||
//
|
||||
// toolStripStatusLabel2
|
||||
//
|
||||
this.toolStripStatusLabel2.Name = "toolStripStatusLabel2";
|
||||
this.toolStripStatusLabel2.Size = new System.Drawing.Size(0, 17);
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1072, 683);
|
||||
this.Controls.Add(this.statusStrip1);
|
||||
this.Controls.Add(this.label7);
|
||||
this.Controls.Add(this.panel1);
|
||||
this.Controls.Add(this.treeView1);
|
||||
@@ -271,6 +298,8 @@
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel1.PerformLayout();
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -296,5 +325,8 @@
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private HslCommunication.Controls.UserButton userButton4;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel2;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +153,7 @@ namespace HslCommunicationNetTestTool
|
||||
}
|
||||
|
||||
label_timeSpend.Text = (DateTime.Now - start).TotalSeconds.ToString("F3");
|
||||
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
|
||||
@@ -117,4 +117,7 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||