主要技术问题:windows,linux等系统采用LITTLE_ENDIAN字节序,而java自身采用BIG_ENGIAN字节序,BIG_ENGIAN是指低地址存放最高有效字节(MSB),而LITTLE_ENDIAN则是低地址存放最低有效字节。Java程序写的客户程序端同c++的服务端程序交互时结构体的某些数据类型需要转换字节序。本文解决方法,java客户端程序发送数据时做相应的转换字节序,等收到数据时再做一次字节序的转换。
现在的网络程序多数采用可靠交付的TCP协议,其采用字节流的传输方式,c++程序中用结构体来模拟报头以此界定每次发送的报文。所以网络中整个字节流的格式:报头+数据负载+报头+数据负载……
本文基于c++写服务端和java写客户端应用场景描述。服务端程序收到客户端发送的报文后将原报文做一个回射。
采用报头:
Struct Header{
Intcmd; //标示报文用途
Intlength; //数据负载长度
Intpara1; //服务端处理完结果
Int para2; //服务端处理完结果
Int para3; //服务端处理完结果
}; 此时套接口的读写方式为先读报头,在报头中取出数据负载的长度,然后再读相应字节的数据。
Java客户端代码:
报头类:
publicclassMsgHeader {
privateintcmd;
privateintlength;
privateintpara1;
privateintpara2;
publicint getCmd() {
returncmd;
}
publicvoid setCmd(int cmd) {
this.cmd = cmd;
}
publicint getLength() {
returnlength;
}
publicvoid setLength(int length) {
this.length = length;
}
publicint getPara1() {
returnpara1;
}
publicvoid setPara1(int para1) {
this.para1 = para1;
}
publicint getPara2() {
returnpara2;
}
publicvoid setPara2(int para2) {
this.para2 = para2;
}
publicint getPara3() {
returnpara3;
}
publicvoid setPara3(int para3) {
this.para3 = para3;
}
privateintpara3;
public MsgHeader()
{
this.cmd = 0;
this.length = 0;
this.para1 = 0;
this.para2 = 0;
this.para3 = 0;
}
public MsgHeader(int cmd,int length,int para1,int para2,int para3){
this.cmd=cmd;
this.length= length;
this.para1 = para1;
this.para2 = para2;
this.para3 = para3;
}
}
公共操作类:
publicclassCommon {
//字节序转换
publicstaticbyte[] toLH(int n) {
byte[] b =newbyte[4];
b[0]= (byte)(n & 0xff);
b[1]= (byte)(n >> 8 & 0xff);
b[2]= (byte)(n >> 16 & 0xff);
b[3]= (byte)(n >> 24 & 0xff);
return b;
}
//btye数组转换为int型
publicstaticint bytes2Integer(byte[] byteVal) {
int result = 0;
for (int i = 0; i < byteVal.length; i++) {
int tmpVal = (byteVal[i]<< (8 * (3 - i)));
switch (i) {
case 0:
tmpVal= tmpVal & 0xFF000000;
break;
case 1:
tmpVal= tmpVal & 0x00FF0000;
break;
case 2:
tmpVal= tmpVal & 0x0000FF00;
break;
case 3:
tmpVal= tmpVal & 0x000000FF;
break;
}
result= result | tmpVal;
}
return result;
}
}
协议类:
publicclassProtocol {
publicstaticfinalintPORTAL_DBC_INSTALLSYSTEM= 0x05000030;
publicstaticfinalintPORTAL_DBC_INSTALLSYSTEM_ACK= 0x05000031;
/*
* add all protocol
*
*
*
*/
}
数据收发类:
publicclassDBCAgent {
private Socketsocket = null;
privatebyte[]buffer;
public DBCAgent() {
try {
this.socket =new Socket("192.168.9.64",8886);
}catch(UnknownHostException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
//收数据
publicvoid recvData()throws IOException {
byte[] recvHead =newbyte[4];
int cForm;
intcmd, length, para1,para2, para3;
// readcmd转换字节序
socket.getInputStream().read(recvHead,0, 4);
cForm= Common.bytes2Integer(recvHead);
cmd= Common.bytes2Integer(Common.toLH(cForm));
// read length转换字节序
socket.getInputStream().read(recvHead,0, 4);
cForm= Common.bytes2Integer(recvHead);
length= Common.bytes2Integer(Common.toLH(cForm));
// read para1转换字节序
socket.getInputStream().read(recvHead,0, 4);
cForm= Common.bytes2Integer(recvHead);
para1= Common.bytes2Integer(Common.toLH(cForm));
// read para2转换字节序
socket.getInputStream().read(recvHead,0, 4);
cForm= Common.bytes2Integer(recvHead);
para2= Common.bytes2Integer(Common.toLH(cForm));
// read para3转换字节序
socket.getInputStream().read(recvHead,0, 4);
cForm= Common.bytes2Integer(recvHead);
para3= Common.bytes2Integer(Common.toLH(cForm));
byte[] recvData =newbyte[length];
// read data
socket.getInputStream().read(recvData,0, length);
StringDataStr = newString(recvData);
System.out.println(DataStr);
}
发数据类:
publicboolean sendData(String data) {
byte[] temp =null;
MsgHeaderheader = newMsgHeader();
header.setLength(data.length());
this.buffer =newbyte[data.length() + 20];
// addcmd 转换字节序
temp= Common.toLH(Protocol.PORTAL_DBC_INSTALLSYSTEM);
System.arraycopy(temp,0,buffer,0, 4);
// addlength转换字节序
temp= Common.toLH(header.getLength());
System.arraycopy(temp,0,buffer,4, 4);
// add para1转换字节序
temp= Common.toLH(header.getPara1());
System.arraycopy(temp,0,buffer,8, 4);
// add para2转换字节序
temp= Common.toLH(header.getPara2());
System.arraycopy(temp,0,buffer,12, 4);
// add para3转换字节序
temp= Common.toLH(header.getPara3());
System.arraycopy(temp,0,buffer,16, 4);
System.arraycopy(data.getBytes(),0,buffer,20, data.length());
try {
socket.getOutputStream().write(this.buffer);
}catch(IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
returntrue;
}
}
测试类:
publicclassTest {
/**
* @param args
* @throws IOException
*/
publicstaticvoid main(String[] args)throws IOException {
//TODO Auto-generated method stub
DBCAgentdbcAgent = newDBCAgent();
//发送数据
dbcAgent.sendData("Helloaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
//接收数据
dbcAgent.recvData();
try {
Thread.sleep(10000);
}catch(InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}