主要是看代码分析别人写的发送结构体思路,如内存补0操作:

package com.cvicse.naba.service.impl.user;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*
* 描述:
* <p>
*     用户操作数据接口实现类。
* </p>
* 创建日期:2012-7-9 下午3:39:46<br>
*
* @author:tianyj<br>
* @update:$Date$<br>
* @version:$Revision$<br>
* @since 1.0.0
*/
public class UserManageSrvImpl implements IUserManageSrv {
private static final int STRUCTS_LENGTH = 316;
private IMessageManSrv messageManSrv;
/**
* 保存用户信息到后台
*
* @param user
*           当前登陆user对象
* @param map
*           添加的数据信息
* @return boolean
*           成功与否,true成功;false失败
* @throws Exception
*/
@Override
public String saveUser(CB_User user, Map<String, String> map) throws Exception {
// 方法坐标
user.setC_x(20);
user.setC_y(1);
// 保存前台传递的用户数据信息
// String userInfo = this.getSaveUserMessage(map);
byte[] returnMsg = messageManSrv.exeCommand(user, getSaveUserMessage(map));
String result = null;
if (returnMsg != null) {
if (handleResult(returnMsg)) {
result = "true";
} else {
result = "false";
}
} else {
result = "logout";
}
// 处理后台返回的操作结果
return result;
}
/**
* 更新用户信息,
* 只是调用后台的方法不同 通过设置user.setC_X和user.setC_Y方法坐标确定
* @param user
*            user对象,主要是方法坐标
* @param map
*            更新的信息
* @return
* @throws Exception
*/
@Override
public String updateUser(CB_User user, Map<String, String> map) throws Exception {
user.setC_x(20);
user.setC_y(4);
// 更新前台需要更新的用户信息
// String userInfo = this.getUpdateUserMessage(map);
byte[] returnMsg = messageManSrv.exeCommand(user, getUpdateUserMessage(map));
String result = null;
if (returnMsg != null) {
if (handleResult(returnMsg)) {
result = "true";
} else {
result = "false";
}
} else {
result = "logout";
}
// 处理后台操作返回的结果
return result;
}
/**
* 修改用户登陆密码,没有用到暂时
* @param user
* @param map
* @throws Exception
* @return
*/
@Override
public boolean updatePassword(CB_User user, Map<String, String> map) throws Exception {
// TODO Auto-generated method stub
String passInfo = "";
byte[] returnMsg = messageManSrv.exeCommand(user, passInfo);
// 处理后台操作返回的结果
return handleResult(returnMsg);
}
/**
* 删除用户
* @parma user
*           当前登陆user对象
* @param str
*           要删除的user的ID
* @throws Exception
*
* @return boolean
*           返回是否删除成功:true成功;false失败
*/
@Override
public String deleteUser(CB_User user, String str) throws Exception {
user.setC_x(20);
user.setC_y(3);
// 处理返回的信息
byte[] returnMsg = messageManSrv.exeCommand(user, str);
String result = null;
if (returnMsg != null && handleResult(returnMsg)) {
if (handleResult(returnMsg)) {
result = "true";
} else {
result = "false";
}
} else {
result = "logout";
}
return result;
}
/**
* 获得单个用户信息
*/
@Override
public Map<String, String> getUserMap(CB_User user, String userID) throws Exception {
// 处理后台传递的字符串进行解析
Map<String, String> map = null;
byte[] returnMsg = messageManSrv.exeCommand(user, "");
// 处理字节转换为CB_User
byte[] struct = new byte[returnMsg.length - 7];
System.arraycopy(returnMsg, 7, struct, 0, returnMsg.length - 7);
map = this.getUserInfoFromByte(struct);
return map;
}
/**
* 返回的returnMsg格式【4个字节+1个字节+2个字节+结构体列表字节】
* 4个字节表示传递长度但是不包括该4个字节在内 1个字节表示成功或者失败
* 2个字节表示调用后台的方法坐标 结构体字节:每个结构体都是固定长度,
* 不足补0,需要把结构体列表 进行解析处理
*/
@Override
public List<Map<String, String>> getUserListMap(CB_User user) throws Exception {
// 设置调用后台的方法坐标
user.setC_x(20);
user.setC_y(2);
// 处理后台传递的用户信息列表
List<Map<String, String>> list = null;
// 执行后台程序返回结果
byte[] returnMsg = messageManSrv.exeCommand(user, "");
if (returnMsg != null) {
// 后台处理成功,进行解析字符串
if (handleResult(returnMsg)) {
// 处理字节转换为List进行返回,returnMsg.length-7表示结构体列表长度
byte[] structs = new byte[returnMsg.length - 7];
// 把结构体列表信息字节复制到另外的字节数组,以便处理
System.arraycopy(returnMsg, 7, structs, 0, returnMsg.length - 7);
// 处理结构体数组,返回List<Map>,Map中存放一个结构体信息
list = this.getUserInfoListFromByte(structs);
}
} else {
// 处理超时登陆
list = new ArrayList<Map<String, String>>();
Map<String, String> map = new HashMap<String, String>();
map.put("logout", "logout");
list.add(map);
}
return list;
}
/**
* 解析后台操作的结果
*
* @param msg
* @return
*/
private boolean handleResult(byte[] msg) {
boolean flag = false;
if (msg.length >= 7) {
// 消息【4个字节+1个字节+2个字节+n个字节】
int result = msg[4];
if (0 == result) {
flag = true;
}
}
return flag;
}
/**
* 依赖注入IMessageManSrv
*
* @param messageManSrv
*/
public void setMesageManSrv(IMessageManSrv messageManSrv) {
this.messageManSrv = messageManSrv;
}
/**
* 释放注入的IMessageManSrv
*
* @param messageManSrv
*/
public void unSetMessageManSrv(IMessageManSrv messageManSrv) {
this.messageManSrv = null;
}
/**
* 封装后台结构体,传递给后台进行存储操作
* typedef struct {
*   unsigned char cmdtype;
*   unsigned char subcmd;
*  unsigned char operate; //1.add, 2.change添加、修改
*  unsigned char passflag;//是否采用USB-KEY方式登录
*  unsigned char priority;
*  unsigned char state;---//状态,禁用与否
*  空两个字节
*  int permission;
*  int authtype;
*  unsigned char userid[16];//用户ID
*  unsigned char username[16];//用户名
*  unsigned char passfirst[16];//密码
*  unsigned char passsecond[16];
*  unsigned char emailaddr[64];//邮箱
*  unsigned char dept[32];//部门
*  unsigned char mobile[16];//电话
*   unsigned char role[16];//角色
*   unsigned char memo[128];//描述
* } PKT_USER_REQ;
*
* @param map
* @return
*/
private byte[] getSaveUserMessage(Map<String, String> map) {
/*StringBuffer msg = new StringBuffer();*/
byte[] msgByte = new byte[336];
byte[] preSixMsg = new byte[6];
preSixMsg[0] = 0;// cmdtype
preSixMsg[1] = 0;// subcmd
preSixMsg[2] = 1;// operate 1.add, 2.change添加、修改
// passflag是否采用USB-KEY方式登录
preSixMsg[3] = Byte.parseByte(ObjectUtils.toString(map.get("isUkey")));
preSixMsg[4] = 0;// priority
// state状态,禁用与否
preSixMsg[5] = Byte.parseByte(ObjectUtils.toString(map.get("state")));
System.arraycopy(preSixMsg, 0, msgByte, 0, preSixMsg.length);
// 补零操作
byte[] completeZero = {0,0};
System.arraycopy(completeZero, 0, msgByte, 6, completeZero.length);
byte[] permissionByte = ByteConvert.intToLBytes(
Integer.parseInt(ObjectUtils.toString(map.get("permission"))));//{0, 0, 0, 0};
System.arraycopy(permissionByte, 0, msgByte, 8, permissionByte.length);
// permissionByte[0] = Byte.parseByte(ObjectUtils.toString(map.get("permission")),2);
byte[] authtypeByte = {0, 0, 0, 0};
System.arraycopy(authtypeByte, 0, msgByte, 12, authtypeByte.length);
// 用户ID构造字节数组,不足16个字节补0
byte[] userid = new byte[16];
userid = buildByteArray(ObjectUtils.toString(map.get("userId")).getBytes(), userid);
System.arraycopy(userid, 0, msgByte, 16, userid.length);
// 用户名字节数组,不足16个字节补0
byte[] username = new byte[16];
username = buildByteArray(ObjectUtils.toString(map.get("userName")).getBytes(), username);
System.arraycopy(username, 0, msgByte, 32, username.length);
// 密码字节数组,不足16个字节补0
byte[] passfirst = new byte[16];
passfirst = buildByteArray(ObjectUtils.toString(map.get("password")).getBytes(), passfirst);
System.arraycopy(passfirst, 0, msgByte, 48, passfirst.length);
// 二次密码
byte[] passsecond = new byte[16];
passsecond = buildByteArray(ByteConvert.intToBytes(0), passsecond);
System.arraycopy(passsecond, 0, msgByte, 64, passsecond.length);
// 邮箱字节数组,不足64个字节补0
byte[] emailaddr = new byte[64];
emailaddr = buildByteArray(ObjectUtils.toString(map.get("email")).getBytes(), emailaddr);
System.arraycopy(emailaddr, 0, msgByte, 80, emailaddr.length);
// 部门字节数组,不足32个字节补0
byte[] dept = new byte[32];
dept = buildByteArray(ObjectUtils.toString(map.get("dept")).getBytes(), dept);
System.arraycopy(dept, 0, msgByte, 144, dept.length);
// 电话
byte[] mobile = new byte[16];
mobile = buildByteArray(ObjectUtils.toString(map.get("mobile")).getBytes(), mobile);
System.arraycopy(mobile, 0, msgByte, 176, mobile.length);
// 角色
byte[] role = new byte[16];
role = buildByteArray(ObjectUtils.toString(map.get("role")).getBytes(), role);
System.arraycopy(role, 0, msgByte, 192, role.length);
// 描述
byte[] memo = new byte[128];
memo = buildByteArray(ObjectUtils.toString(map.get("memo")).getBytes(), memo);
System.arraycopy(memo, 0, msgByte, 208, memo.length);
/*msg.append(ChangeCharSet.toUTF8(preSixMsg))
.append(ChangeCharSet.toUTF8(completeZero))
.append(ChangeCharSet.toUTF8(permissionByte))
.append(ChangeCharSet.toUTF8(authtypeByte))
.append(ChangeCharSet.toUTF8(userid))
.append(ChangeCharSet.toUTF8(username))
.append(ChangeCharSet.toUTF8(passfirst))
.append(ChangeCharSet.toUTF8(passsecond))
.append(ChangeCharSet.toUTF8(emailaddr))
.append(ChangeCharSet.toUTF8(dept))
.append(ChangeCharSet.toUTF8(mobile))
.append(ChangeCharSet.toUTF8(role))
.append(ChangeCharSet.toUTF8(memo));*/
return msgByte;
}
/**
* typedef struct {
*   unsigned char cmdtype;
*   unsigned char subcmd;
*   unsigned char userid[USER_NAME_SIZE];
*   unsigned char chpass; //0:不修改  1:修改
*   unsigned char oldpass[USER_PASS_SIZE];
*   unsigned char newpass[USER_PASS_SIZE];
*   unsigned char passflag;
*   unsigned char priority;
*   unsigned char state;
*   int permission;
*   int authtype;
*   unsigned char username[USER_NAME_SIZE];
*   unsigned char passfirst[USER_PASS_SIZE];
*   unsigned char passsecond[USER_PASS_SIZE];
*   unsigned char emailaddr[USER_MAIL_SIZE];
*   unsigned char dept[32];
*   unsigned char mobile[USER_TLE_SIZE];
*  unsigned char role[USER_ROLE_SIZE];
*   unsigned char memo[USER_MEMO_LEN];
* } PKT_EDIT_USER_REQ ;
*
* @param map
* @return
*/
private byte[] getUpdateUserMessage(Map<String, String> map){
// StringBuffer msg = new StringBuffer();
byte[] msgByte = new byte[368];
byte[] preTwo = new byte[2];
preTwo[0] = 0;
preTwo[1] = 0;
System.arraycopy(preTwo, 0, msgByte, 0, preTwo.length);
// 用户ID构造字节数组,不足16个字节补0
byte[] userid = new byte[16];
userid = buildByteArray(ObjectUtils.toString(map.get("userId")).getBytes(), userid);
System.arraycopy(userid, 0, msgByte, 2, userid.length);
// 是否修改密码
byte[] chpass = new byte[1];
chpass[0] = Byte.parseByte(ObjectUtils.toString(map.get("chpass")));
System.arraycopy(chpass, 0, msgByte, 18, chpass.length);
// 旧密码
byte[] oldPass = new byte[16];
// 新密码
byte[] newPass = new byte[16];
// 修改密码为1
if ("1".equals(ObjectUtils.toString(map.get("chpass")))) {
oldPass = buildByteArray(ObjectUtils.toString(map.get("oldPass")).getBytes(), oldPass);
newPass = buildByteArray(ObjectUtils.toString(map.get("newPass")).getBytes(), newPass);
}
System.arraycopy(oldPass, 0, msgByte, 19, oldPass.length);
System.arraycopy(newPass, 0, msgByte, 35, newPass.length);
// 是否使用ukey
byte[] passflag = new byte[1];
passflag[0] = Byte.parseByte(ObjectUtils.toString(map.get("isUkey")));
System.arraycopy(passflag, 0, msgByte, 51, passflag.length);
// priority,无用
byte[] priority = {0};
System.arraycopy(priority, 0, msgByte, 52, priority.length);
// 用户状态,是否被禁用
byte[] state = new byte[1];
state[0] = Byte.parseByte(ObjectUtils.toString(map.get("state")));
System.arraycopy(state, 0, msgByte, 53, state.length);
// 补零
byte[] completeZero = {0, 0};
System.arraycopy(completeZero, 0, msgByte, 54, completeZero.length);
// 无用
byte[] permissionByte = ByteConvert.intToLBytes(
Integer.parseInt(ObjectUtils.toString(map.get("permission"))));
System.arraycopy(permissionByte, 0, msgByte, 56, permissionByte.length);
byte[] authtypeByte = {0, 0, 0, 0};
System.arraycopy(authtypeByte, 0, msgByte, 60, authtypeByte.length);
// 用户名字节数组,不足16个字节补0
byte[] username = new byte[16];
username = buildByteArray(ObjectUtils.toString(map.get("userName")).getBytes(), username);
System.arraycopy(username, 0, msgByte, 64, username.length);
// 密码字节数组,不足16个字节补0,不用
byte[] passfirst = new byte[16];
passfirst = buildByteArray(ByteConvert.intToBytes(0), passfirst);
System.arraycopy(passfirst, 0, msgByte, 80, passfirst.length);
// 二次密码,不用
byte[] passsecond = new byte[16];
passsecond = buildByteArray(ByteConvert.intToBytes(0), passsecond);
System.arraycopy(passsecond, 0, msgByte, 96, passsecond.length);
// 邮箱字节数组,不足64个字节补0
byte[] emailaddr = new byte[64];
emailaddr = buildByteArray(ObjectUtils.toString(map.get("email")).getBytes(), emailaddr);
System.arraycopy(emailaddr, 0, msgByte, 112, emailaddr.length);
// 部门字节数组,不足32个字节补0
byte[] dept = new byte[32];
dept = buildByteArray(ObjectUtils.toString(map.get("dept")).getBytes(), dept);
System.arraycopy(dept, 0, msgByte, 176, dept.length);
// 电话
byte[] mobile = new byte[16];
mobile = buildByteArray(ObjectUtils.toString(map.get("mobile")).getBytes(), mobile);
System.arraycopy(mobile, 0, msgByte, 208, mobile.length);
// 角色
byte[] role = new byte[16];
role = buildByteArray(ObjectUtils.toString(map.get("role")).getBytes(), role);
System.arraycopy(role, 0, msgByte, 224, role.length);
// 描述
byte[] memo = new byte[128];
memo = buildByteArray(ObjectUtils.toString(map.get("memo")).getBytes(), memo);
System.arraycopy(memo, 0, msgByte, 240, memo.length);
/*msg//.append(ChangeCharSet.toUTF8(preTwo))
.append(ChangeCharSet.toUTF8(userid))
.append(ChangeCharSet.toUTF8(chpass))
.append(ChangeCharSet.toUTF8(oldPass))
.append(ChangeCharSet.toUTF8(newPass))
.append(ChangeCharSet.toUTF8(passflag))
.append(ChangeCharSet.toUTF8(priority))
.append(ChangeCharSet.toUTF8(state))
.append(ChangeCharSet.toUTF8(completeZero))
.append(ChangeCharSet.toUTF8(permissionByte))
.append(ChangeCharSet.toUTF8(authtypeByte))
.append(ChangeCharSet.toUTF8(username))
.append(ChangeCharSet.toUTF8(passfirst))
.append(ChangeCharSet.toUTF8(passsecond))
.append(ChangeCharSet.toUTF8(emailaddr))
.append(ChangeCharSet.toUTF8(dept))
.append(ChangeCharSet.toUTF8(mobile))
.append(ChangeCharSet.toUTF8(role))
.append(ChangeCharSet.toUTF8(memo));*/
return msgByte;
}
/**
* 拷贝字节数组,不足长度补0,0的编码为48;
*
* @param srcArry
* @param destArry
* @param length
* @return
*/
private byte[] buildByteArray(byte[] srcArry, byte[] destArry) {
int length = srcArry.length;
if (srcArry.length > destArry.length) {
length = destArry.length;
}
System.arraycopy(srcArry, 0, destArry, 0, length);
return destArry;
}
/**
* 处理后台传递过来的多个结构体的方法,固定一个结构体的长度为313个字节 把结构体数组字节分割成单个结构体数组,然后进行对每个结构体数组进行
* 解析,存放到Map中,Map中对应的是一个结构体,也就是用户信息
*
* @param structs
*            结构体列表字节数组
* @return
*/
private List<Map<String, String>> getUserInfoListFromByte(byte[] structs) throws Exception {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
// 把结构体字节数组进行分割成多个结构体
for (int i = 0; i < structs.length / STRUCTS_LENGTH; i++) {
// 复制到新的byte数组
byte[] struct = new byte[STRUCTS_LENGTH];
// 在原数组复制操作的起始位置
int srcPosition = i * STRUCTS_LENGTH;
System.arraycopy(structs, srcPosition, struct, 0, STRUCTS_LENGTH);
// 解析单个结构体
Map<String, String> temp = getUserInfoFromByte(struct);
list.add(temp);
}
return list;
}
/**
* 请求返回的用户列表结构体定义
* typedef struct {
* 0 unsigned char passflag; // 是否启用UKey
* 1 unsigned char priority;
* 2 unsigned char state;
* 3 unsigned char reserve;
* 4 unsigned char authtype;
* 5 unsigned char userid[16];
* 21 unsigned char username[16];
* 37 unsigned char emailaddr[64];
* 101 unsigned char dept[32];
* 133 unsigned char mobile[16];
* 149 unsigned char role[16];
* 168 int permission;
* 172 unsigned int createtime;
* 176 unsigned int lasttime;
* 180 int logintimes;
* 184 int failtimes; 181 unsigned
* 188 char memo[128]; 185 } PKT_USER_LIST;
*
* @param struct
* @return
* @throws Exception
*/
private Map<String, String> getUserInfoFromByte(byte[] struct) throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("isUkey", String.valueOf(struct[0]));
map.put("state", String.valueOf(struct[2]));
map.put("userId", getFieldValue(struct, 5, 16, "string"));
map.put("userName", getFieldValue(struct, 21, 16, "string"));
map.put("email", getFieldValue(struct, 37, 64, "string"));
map.put("dept", getFieldValue(struct, 101, 32, "string"));
map.put("mobile", getFieldValue(struct, 133, 16, "string"));
map.put("role", getFieldValue(struct, 149, 16, "string"));
map.put("permission", getFieldValue(struct, 168, 4, "integer"));
map.put("createtime", getFieldValue(struct, 172, 4, "time"));
map.put("lasttime", getFieldValue(struct, 176, 4, "time"));
map.put("logintimes", getFieldValue(struct, 180, 4, "integer"));
map.put("failtimes", getFieldValue(struct, 184, 4, "integer"));
map.put("memo", getFieldValue(struct, 188, 128, "string"));
return map;
}
/**
* 处理结构体中单个数据, 从给定的字节数组中取出特定位置的字节转换为字符串
*
* @param bty
* @param srcPosition
* @param length
* @return
*/
private String getFieldValue(byte[] bty, int srcPosition, int length, String converFlag) throws Exception {
// 拷贝规定的字节长度
byte[] temp = new byte[length];
String returnStr = "";
System.arraycopy(bty, srcPosition, temp, 0, length);
if ("".equals(converFlag) || "string".equals(converFlag)) {
// 记录有效字节的长度
int position = 0;
/*
* 字节数组从后面截取,到第一个不为0停止,记录位置,0-position为有效字节
* 例子:[12,52,89,0,0,0,0],有效字节为前面的非0字节
*/
for (int i = temp.length - 1; i >= 0; i--) {
position = i;
if (temp[i] != 0) {
break;
}
}
// 把有效字节转为为字符串
byte[] validValue = new byte[position + 1];
System.arraycopy(temp, 0, validValue, 0, position + 1);
returnStr = new String(validValue);
} else if ("time".equals(converFlag)) {
long time = ByteConvert.lBytesToInt(temp);
returnStr = ObjectUtils.get24Time(time*1000);
/*Date date = new Date(time*1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
returnStr = sdf.format(date);*/
} else if ("integer".equals(converFlag)) {
returnStr = String.valueOf(ByteConvert.lBytesToInt(temp));
}
return returnStr;
}
}

java和C结构体通信相关推荐

  1. Java中发送结构体

    http://blog.csdn.net/xwchen/article/details/1585908 最近给个朋友做个网站的客户端,使用C/S模式,Client为VC6开发,Server为Java, ...

  2. java 链表放置结构体_结构体和它在链表中的使用

    一.结构体 由不同类型的数据组合成一个整体,以便引用,这些组合在一个整体中的数据是互相联系的. 1.1如何声明结构体呢? struct 结构体名  //结构体名字用作结构体类型的标志 {成员列表}; ...

  3. java读取C++结构体,类型转换

    package com.struct.method; import java.io.EOFException; import java.io.FilterInputStream; import jav ...

  4. Java实现结构体,让字节流封送简单起来

    和C/C++不同,Java中没有结构体,联合体.这是Java作为高级语言的进步,但也使得它在进行网络字节流封送上显得捉襟见肘. 这里所指的是在进行网络编程,串口编程等需要和某些C语言中结构体形式定义的 ...

  5. android jni 结构体_Android应用开发Android JNI-c/c++调用java方法

    本文将带你了解Android应用开发Android JNI-c/c++调用java方法,希望本文对大家学Android有所帮助. " Android   JNI-c/c++调用java方法, ...

  6. java中结构体入参_JNA中自定义结构体如何传参?

    1.先给出C的头文件里的结构体: typedef struct DetectionZone { Zone zone; DetectionZoneParam param; } DetectionZone ...

  7. Java中如何实现结构体?如何对结构体进行排序?

    ***今天在做老师布置的编程题时,遇到了本题.感觉这道题如果用C++来解决的话,用结构体比较好吧!哈哈哈,可能还有其他的好方法,但我目前想到的是用结构体来解决比较合理.Java中有结构体吗?如果有,它 ...

  8. JNI调用c++函数,该函数的参数是结构体(——对象的传递)

    第三方C++函数接口为 int api_get_logfile(Struct fileinfo tfile),参数是个结构体,且套了另一个结构体: struct fileinfo{  char *fu ...

  9. 深入解析JNA—模拟C语言结构体

    原帖:http://blog.csdn.net/shendl/article/details/3599849 深入解析JNA-模拟C语言结构体 前言 前几天写<JNA--JNI终结者>一文 ...

最新文章

  1. Openstack_单元测试
  2. Material Design Lite,简洁惊艳的前端工具箱。
  3. html:web前端开发规范
  4. e3d教程做logo教程_看了教程还是不会做平面设计?关键的方法给你揭秘!附450集教程...
  5. 如何给python升级_python升级后,如何给virtualenv里的python进行升级
  6. 130825组队赛-Regionals 2012, North America - East Central NA
  7. 快速下载 Android framework 源码
  8. SaltStacks三:写法和高级状态
  9. Cocos2D开发的iPhone游戏的教程
  10. 基本面分析:原理、类型和使用方法
  11. 鱼香ROS网站上线|一行代码安装ROS/ROS2/解决rosdep问题|小鱼脚本
  12. 毕设-基于LoRa的智能农业大棚(二)
  13. http://ajava.org/readbook/java/javaemail/11239.html Mime 邮件详解
  14. 从0编写区块链:用python解释区块链最基本原理
  15. Animate中如何创建辅助线
  16. 关于R批量导入excel的方法
  17. FPGA打砖块游戏设计(有上板照片)VHDL
  18. 期货数据读取python从新浪财经
  19. 循环水旁流水处理器的工作原理
  20. 【工具资源】—— Gitbash命令行上传代码到Github仓库

热门文章

  1. 腾讯企业级消息中间件CMQ技术解密
  2. 浅析低延迟直播协议设计:RTP/RTCP
  3. Python Virtualenv Anaconda
  4. Android NFC开发
  5. centos7 redis5.0以前版本 部署集群示例 - 第二篇
  6. Your local changes would be overwritten by merge. Commit, stash or revert them to proceed.
  7. 大剑无锋之HTTP连接、Tcp三次握手四次挥手、Tcp状态
  8. P8实战(二):分布式锁前置技能 etcd 集群搭建
  9. Java高新技术笔记:反射、多线程、泛型、枚举、javaBean、代理
  10. Leet Code OJ 235. Lowest Common Ancestor of a Binary Search Tree [Difficulty: Easy]