1. 程式人生 > >java 和C++ Socket程式傳送結構體

java 和C++ Socket程式傳送結構體

       主要技術問題: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();

        }

    }

}