java和C结构体通信

来源:互联网 发布:office for mac 破解 编辑:程序博客网 时间:2024/05/18 02:00

package com.cvicse.naba.service.impl.user;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.cvicse.naba.common.utils.ByteConvert;import com.cvicse.naba.common.utils.ObjectUtils;import com.cvicse.naba.service.api.msg.IMessageManSrv;import com.cvicse.naba.service.api.user.IUserManageSrv;import com.cvicse.unicorn.framework.entity.CB_User;/** *  *  * 描述: * <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 */@Overridepublic 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 */@Overridepublic 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 stubString passInfo = "";byte[] returnMsg = messageManSrv.exeCommand(user, passInfo);// 处理后台操作返回的结果    return handleResult(returnMsg);    }/** * 删除用户 * @parma user * 当前登陆user对象 * @param str * 要删除的user的ID * @throws Exception *  * @return boolean  * 返回是否删除成功:true成功;false失败 */@Overridepublic 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;}/** * 获得单个用户信息 */@Overridepublic Map<String, String> getUserMap(CB_User user, String userID) throws Exception {// 处理后台传递的字符串进行解析Map<String, String> map = null;byte[] returnMsg = messageManSrv.exeCommand(user, "");// 处理字节转换为CB_Userbyte[] 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,需要把结构体列表 进行解析处理 */@Overridepublic 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;// cmdtypepreSixMsg[1] = 0;// subcmdpreSixMsg[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个字节补0byte[] userid = new byte[16];userid = buildByteArray(ObjectUtils.toString(map.get("userId")).getBytes(), userid);System.arraycopy(userid, 0, msgByte, 16, userid.length);// 用户名字节数组,不足16个字节补0byte[] username = new byte[16];username = buildByteArray(ObjectUtils.toString(map.get("userName")).getBytes(), username);System.arraycopy(username, 0, msgByte, 32, username.length);// 密码字节数组,不足16个字节补0byte[] 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个字节补0byte[] emailaddr = new byte[64];emailaddr = buildByteArray(ObjectUtils.toString(map.get("email")).getBytes(), emailaddr);System.arraycopy(emailaddr, 0, msgByte, 80, emailaddr.length);// 部门字节数组,不足32个字节补0byte[] 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个字节补0byte[] 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];// 修改密码为1if ("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);// 是否使用ukeybyte[] 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个字节补0byte[] 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个字节补0byte[] emailaddr = new byte[64];emailaddr = buildByteArray(ObjectUtils.toString(map.get("email")).getBytes(), emailaddr);System.arraycopy(emailaddr, 0, msgByte, 112, emailaddr.length);// 部门字节数组,不足32个字节补0byte[] 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;}}

PS:

1、C中int类型的数据在内存中存放和int类型占用的字节数有关,因此有些地方需要补零操作。例如,C在系统中占用4个字节,int类型的数据在内存中存放开始字节是被4整除的地址,通过socket传递过来的字节数组在相应的位置会进行补零(C端进行操作),在Java中解析字节时或者构造相应的结构体字节数组时都要对补零的地方进行操作,去掉补充的零占位字节或者添加相应的补零操作,然后进行传递。

2、在C中的字符串会有结束标识"\0",从Java端传递的数据不要占满整个字节数组,例如:unsigned char emailaddr[64],java字节数组如果填充满了该字符数组,C进行构造该字节数组时会舍去一部分,会造成乱码。注意操作




0 0
原创粉丝点击