通常在做系统集成应用的时候,Java语言会和C语言就数据的传输和共享达成一致的协议,服务于相应的应用。Java 和C 语言通信的常用方式,主要有两种:JNI 和socket 字节传输。述说JNI的网上有很多的一堆,现在我就简单说说如何在一种自定义的协议下,完成系统见的通信。
以我本机为例,展示socket字节传输,并解析。先看协议,再直接上代码查看:
验证码 |
Char[8] |
8 |
“PEOPLE10 ” |
数据总长 |
int |
4 |
后续所有数据的长度 |
协议类型 |
short |
2 |
协议类型,类型含义如下: 3、数据集成系统 |
保留字段 |
Char[16] |
当前版本暂时保留 | |
命令类型 |
short |
2 |
命令类型,详细如下 |
8增加关系类型 |
rel num |
Int |
4 |
要操作的关系类型个数 |
rel len |
Int |
4 |
关系类型名称长度 | |
rel name |
Char* |
Type len |
关系名称 | |
Rel weight |
Int |
4 |
关系权重 | |
Is_multi |
char |
1 |
是否多值,0为单值,1为多值 | |
…… |
…… |
…… |
…… |
扩展长度 |
int |
4 |
扩展长度,为以后扩展使用,固定为0 |
扩展字段 |
Char* |
扩展长度 |
不需要填写此值 |
先看客户端干货:
/**
* 发送数据.
*/
public static void sendMsg() {
Socket socket = null;
OutputStream outs = null;
try {
socket = new Socket("127.0.0.1", TestServer.PORT);
outs = socket.getOutputStream();
short type = 3;
byte[] datas = assemblyRelationshipProtocol(type);
outs.write(datas,0,datas.length);
outs.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
outs.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static byte[] assemblyRelationshipProtocol(int type) {
try {
List<byte[]> protoList = new ArrayList<byte[]>();
int dataLen = 0;
int relNum = 1;
byte[] numByte = DataConvert.intToByteArray(relNum);
dataLen += 4;
String relName = "朋友";
byte[] nameByte = relName.getBytes();
int relNameLen = nameByte.length;
byte[] lenByte = DataConvert.intToByteArray(relNameLen);
dataLen += 4;
dataLen += relNameLen;
int right = 1;
byte[] rightByte = DataConvert.intToByteArray(right);
dataLen += 4;
String IsMult = "1";
byte[] Is_multiByte = IsMult.getBytes();
dataLen += 1;
byte[] headProtoByte = null;
short add=8,del=9;
if (type == 1) {
headProtoByte = assemblyHeadProtocol(add, dataLen);
} else {
headProtoByte = assemblyHeadProtocol(del, dataLen);
}
protoList.add(headProtoByte);
protoList.add(numByte);
protoList.add(lenByte);
protoList.add(nameByte);
protoList.add(rightByte);
protoList.add(Is_multiByte);
return DataConvert.sysCopy(protoList);
} catch (Exception e) {
return null;
}
}
public static byte[] assemblyHeadProtocol(short command_type, int total_data_len) {
List<byte[]> protoList = new ArrayList<byte[]>();
String VERIFY_CODE = "PEOPLE10";
byte[] verifyCodeByte = VERIFY_CODE.getBytes();//[8]验证码
byte[] dataLenByte = DataConvert.intToByteArray(total_data_len + 20);//[4]数据总长
short type = 3; //协议类型
byte[] protoTypeByte = DataConvert.shortToBytes(type);//[2]协议类型
byte[] commandTypeByte = DataConvert.shortToBytes(command_type);//[2]命令类型
byte[] retain_field_16 = new byte[16];//16位保留字段
protoList.add(verifyCodeByte);//[8]验证码
protoList.add(dataLenByte);//[4]数据总长
protoList.add(protoTypeByte);//[2]协议类型
protoList.add(retain_field_16);//[16]保留字段
protoList.add(commandTypeByte);//[2]命令类型
byte[] proto = DataConvert.sysCopy(protoList);
System.out.println("最终给的协议数据是:"+new String(proto));
return proto;
}
服务端解析干货:
/**
* 接收socket传递来的数据
*/
public static String accepts() {
ServerSocket serSocket = null;
Socket socket = null;
InputStream ins = null;
BufferedInputStream bis = null;
byte[] byte_identifyCode = null;
String resStr = "";
String verifyCode = "";
try {
serSocket = new ServerSocket(PORT);
socket = serSocket.accept();
ins = socket.getInputStream();
bis = new BufferedInputStream(ins, 1024);
byte_identifyCode = new byte[8];
int nresult = bis.read(byte_identifyCode, 0, 8);
if (nresult < 0) {
System.out.println("读取标准头的前8字节时报错!!");
}
verifyCode = new String(byte_identifyCode); // 验证码
byte[] byte_alllen = new byte[4];
int nresult2 = bis.read(byte_alllen, 0, 4);
int length = DataConvert.bytesToInt(byte_alllen);
if (nresult2 < 0) {
System.out.println("image:对不起,读取标准头的后4个标识长度字节时报错!!");
}
byte[] protoTypeArr = new byte[2];
bis.read(protoTypeArr, 0, 2);
short protoType = DataConvert.bytesToShort(protoTypeArr);
byte[] otherArr = new byte[16];
bis.read(otherArr, 0, 16);
byte[] commandTypeArr = new byte[2];
bis.read(commandTypeArr, 0, 2);
short commandType = DataConvert.bytesToShort(commandTypeArr);
byte[] numbyte = new byte[4];
bis.read(numbyte,0,4);
int num = DataConvert.bytesToInt(numbyte);
byte[] lennamebyte = new byte[4];
bis.read(lennamebyte, 0, 4);
int len = DataConvert.bytesToInt(lennamebyte);
byte[] namebyte = new byte[4];
bis.read(namebyte, 0, 4);
//String relName =new String(namebyte,"utf-8");
String relName =new String(namebyte);
byte[] rightbyte = new byte[4];
bis.read(rightbyte, 0, 4);
int right = DataConvert.bytesToInt(rightbyte);
byte[] ismutilbyte = new byte[1];
bis.read(ismutilbyte,0,1);
String ismutil = new String(ismutilbyte);
return String.valueOf("OK");
} catch (Exception e) {
System.out.println("协议解析发生异常:" + e.getMessage());
resStr = null;
}finally{
try {
if (bis != null) {
bis.close();
}
} catch (Exception e) {
}
}
return resStr;
}
转换的类在:http://blog.youkuaiyun.com/supingemail/article/details/35989103
主意:汉字传输时候,要先传长度,再传汉字。解析时候也是,否则就不能正常解析
想了解更多详细内容:http://download.youkuaiyun.com/detail/supingemail/7602895