新增安卓端模版,目前只具备启动界面和基础通讯功能,有待完善,v1.7.4

This commit is contained in:
dathlin
2017-11-05 09:53:46 +08:00
parent e8c10c048f
commit c84bd71cb7
79 changed files with 5191 additions and 3 deletions

9
AndroidTemplate/.gitignore vendored Normal file
View 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
View 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
View 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
View 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>

View 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
View File

@@ -0,0 +1 @@
/build

View 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
View 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

View File

@@ -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());
}
}

View 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>

View File

@@ -0,0 +1,13 @@
package com.example.HslCommunication.BasicFramework;
/**
* Created by hsl20 on 2017/11/4.
* 静态类,提供许多程序运行的方法
*/
public class SoftBasic {
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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)
{
}
}
}

View File

@@ -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;
}
}
*/
}

View File

@@ -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;
}
}
}

View File

@@ -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)
{
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,11 @@
package com.example.HslCommunication.Profinet;
/**
* Created by DATHLIN on 2017/11/3.
*/
public enum SiemensPLCS {
S1200,
S300,
Smart200,
}

View File

@@ -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读取数据地址格式为I100Q100DB20.100M100以字节为单位
/// </summary>
/// <param name="address">起始地址格式为I100M100Q100DB20.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数据地址格式为I100Q100DB20.100M100以字节为单位
/// </summary>
/// <param name="address">起始地址格式为I100M100Q100DB20.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;
}

View File

@@ -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 = "客户端登录中错误:";
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}

View 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>

View 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>

View File

@@ -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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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>

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View 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>

View 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>

View File

@@ -0,0 +1,3 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>

View 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>

View 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>

View File

@@ -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);
}
}

View 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
}

View 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

Binary file not shown.

View 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
View 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
View 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

View File

@@ -0,0 +1 @@
include ':app'

View File

@@ -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;
}
}

View File

@@ -153,6 +153,7 @@ namespace HslCommunicationNetTestTool
}
label_timeSpend.Text = (DateTime.Now - start).TotalSeconds.ToString("F3");
}
catch(Exception ex)
{

View File

@@ -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>