通过Java套接字发送数据的编码问题?

时间:2016-09-27 18:46:20

标签: java sockets

我有以下代码。我可以很好地读取数据并将数据转换为十六进制。问题是,当我发回Customer时,设备会将其作为String replyMessage = "7E81";收到。怎么了?是由于我的编码,还是在发回之前需要进行一些转换?

"3745"

1 个答案:

答案 0 :(得分:2)

根据聊天中的评论:

  

文件说

     

开始字节(1字节)7e
  消息ID(2字节)01 00
  消息体性质(2字节)00 19
  电话号码。设备(6字节)09 40 27 84 94 70
  消息序列号(2字节)00 01
  信息正文(N字节)00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 09 40 27 84 94 70 00
  检查代码(1Byte)19
  结束字节(1Byte)7E

     

所以开始和终止是7E

     

传出

     

开始字节(1字节)7e
  消息ID(2字节)81 00
  消息体性质(2字节)00 13
  电话号码。设备(6字节)09 40 27 84 94 70
  消息序列号(2字节)00 01
  消息正文(N字节)00 01 00 32 30 31 31 31 31 30 38 31 31 33 33 32 31 39 36
  检查代码(1Byte)9A
  结束字节(1Byte)7e

这意味着所讨论的协议是二进制协议,而不是像您想象的那样发送十六进制字符串的文本协议。因此,对此协议使用OutputStreamWriterInputStreamReaderStringBuildertoHexString()完全错误

接收和发送的每条消息都以固定的13字节标头开头,后跟一个可变长度的主体(标头指定主体长度),并以固定的2字节页脚结束。

考虑到这一点,请尝试更像这样的事情:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

...

w = new DataOutputStream(new BufferedOutputStream(receivedSocketConn1.getOutputStream()));
r = new DataInputStream(new BufferedInputStream(receivedSocketConn1.getInputStream()));

...

if (r.readByte() != 0x7E) // start byte
{
    // ah oh, something went wrong!!
    receivedSocketConn1.close();
    return;
}

int messageID = r.readUnsignedShort();     // message ID
int bodyLen = r.readUnsignedShort();       // message body nature (body length)
byte[] phoneNum = new byte[6];
r.readFully(phoneNum);                     // device phone number
int serialNum = r.readUnsignedShort();     // message serial number
byte[] messageBody = new byte[bodyLen];    // message body
r.readFully(messageBody);
byte checkCode = r.readByte();             // check code

if (r.readByte() != 0x7E) // end byte
{
    // ah oh, something went wrong!!
    receivedSocketConn1.close();
    return;
}

// TODO: validate checkCode if needed...

System.out.println("messageId is : 0x" + Integer.toHexString(messageID));
System.out.println("phoneNum is : " + bytesToHex(phoneNum));
System.out.println("serialNum is : 0x" + Integer.toHexString(serialNum));
System.out.println("messageBody is : " + bytesToHex(messageBody));

// process message data as needed...

switch (messageID)
{
    case 0x100:
    {
        // ...

        byte[] replyBody = new byte[19];
        replyBody[0] = 0x00;
        replyBody[1] = 0x01;
        replyBody[2] = 0x00;
        replyBody[3] = 0x32;
        // and so on...

        checkCode = 0x9A; // calculate as needed...

        w.writeByte(0x7e);               // start byte
        w.writeShort(0x8100);            // message ID
        w.writeShort(replyBody.length);  // message body nature (body length)
        w.write(phoneNum);               // device phone number
        w.writeShort(0x0001);            // message serial number
        w.write(replyBody);              // message body
        w.writeByte(checkCode);          // check code
        w.writeByte(0x7e);               // end byte

        break;
    }

    // other message IDs as needed...
}

w.flush();