简体   繁体   English

通过 TCP 套接字服务器解析 java 中的二进制数据

[英]Parsing binary data in java received over TCP socket server

I have a socket server which keeps listening to incoming requests.我有一个套接字服务器,它一直在监听传入的请求。 The data received will be in the form of binary array of bytes.接收到的数据将采用二进制字节数组的形式。 Data format is something like this.数据格式是这样的。 2321902321221200AA 2321902321221200AA

  • Whereas 1 byte is data begin1个字节是数据开始
  • 4 bits is version 4位是版本
  • 4 bits is data return type 4位是数据返回类型
  • 5 bytes are product code 5个字节是产品代码
  • 2 bytes data length 2字节数据长度

The question is, how to parse the data and segregate the parameters.问题是,如何解析数据和隔离参数。

Thanks in advance!!提前致谢!!

Try java.io.DataInputStream: 尝试java.io.DataInputStream:

    DataInputStream dis = new DataInputStream(in);
    byte b = dis.readByte();
    int version = (b >> 4) & 0xF;
    int returnType = b & 0xF;
    byte[] productCode = new byte[5];
    dis.readFully(productCode);
    int len = dis.readShort() & 0xFFFF;

if use the java binary block parser then code will look like 如果使用Java二进制块解析器,则代码将如下所示

class Parsed { 
  @Bin byte begin; 
  @Bin(type = BinType.BIT) int version; 
  @Bin(type = BinType.BIT) int returnType;
  @Bin byte [] productCode;
  @Bin(type = BinType.USHORT) int dataLength;
}
final Parsed parsed = JBBPParser.prepare("byte begin; bit:4 version; bit:4 returnType; byte [5] productCode; ushort dataLength;")
        .parse(new byte[]{0x23,0x21,(byte)0x90,0x23,0x21,0x22,0x12,0x00,(byte)0xAA})
        .mapTo(Parsed.class);

assertEquals(0x23, parsed.begin);
assertEquals(0x01, parsed.version);
assertEquals(0x02, parsed.returnType);
assertArrayEquals(new byte[]{(byte)0x90,0x23,0x21,0x22,0x12}, parsed.productCode);
assertEquals(0x00AA,parsed.dataLength);

Recommend you a java tool( FastProto ) to parse binary quickly.推荐你一个 java 工具( FastProto )来快速解析二进制文件。

import org.indunet.fastproto.annotation.*;

public class Request {
    @UInt8Type(offset = 0)
    Integer header;  // begin
 
    @UInt8Type(offset = 1)
    @DecodingFormula(lambda = "x -> x >> 4")
    Integer version;  // version

    @UInt8Type(offset = 1)
    @DecodingFormula(lambda = "x -> x & 0x0F")
    Integer returnType;  // return type

    @BinaryType(offset = 2, length = 5)
    byte[] productCode;  // product code

    @UInt16Type(offset = 7)
    Integer length;  // data length
}


byte[] bytes = ... // the binary received
Request request = FastProto.parse(bytes, Request.class);

Maybe you have noticed that FastProto describes the field information in binary data through annotations, which is very simple and efficient.可能你已经注意到,FastProto 通过注解来描述二进制数据中的字段信息,非常简单高效。

If the project can solve your problem, please give a star, thanks.如果项目能解决您的问题,请给个star,谢谢。

GitHub Repo: https://github.com/ind.net/fastproto GitHub 回购: https://github.com/ind.net/fastproto

try {
    char [] cbuf = new char[16];
    char databegin = cbuf[0];
    char [] version = Arrays.copyOfRange(cbuf, 1, 6) 
    char [] product_typep = Arrays.copyOfRange(cbuf, 7, 12)
    char []data_lendth = Arrays.copyOfRange(cbuf, 13, 15)

} catch(Error e){
    System.out.println(e);
}
byte [] data = receiveData ();

int dataBegin = data [0];           // Once field is 1-byte, it is simple!
int version = data [1] & 0x0F;      // Use shift (>>>) and binary "and" (&)
int returnCode =                    // to extract value of fields that are
    (data [1] >>> 4) & 0x0F;        // smaller than one byte
byte [] productCode =               // Copy fixed-size portions of data
    new byte [] {                   // into separate arrays using hardcode
        data [2], data [3],         // (as here),  or System.arrayCopy
        data [4], data [5],         // in case field occupies quite
        data [6]};                  // a many bytes.
int dataLength =                    // Use shift (<<) binary or (|) to 
    (data [7] & 0xFF) |             // Combine several bytes into one integer
    ((data [8] & 0xFF) << 8);       // We assume little-endian encoding here

I would got for some king of package reader: 我会得到一些包装阅读器之王:

class Record {

   .....

   Record static fromBytes(byte[] bytes) {
       // here use ByteBuffer or DataInputStream to extract filds
       ......
   }
}


Record readNextRecord(InputStream in) {
    int len = in.read() && 0xFF;
    byte[] data = new byte[len];
    in.read(data);
    return Record.fromBytes(data)
}



{
  InputStream in = ....;
  Record r readNextRecord(in);
  process (r);
}

Of course you need to add error handling. 当然,您需要添加错误处理。 In general, for something which should run reliable, I will suggest to use NIO framework like Grizzly or Netty. 通常,对于应该可靠运行的东西,我建议使用Grizzly或Netty之类的NIO框架。

You might get the data via the ByteArrayOutputStream And then parse the bytes by applying masks (mainly AND, OR). 您可以通过ByteArrayOutputStream获取数据,然后通过应用掩码(主要是AND,OR)来解析字节。

Take a look at This question 看看这个问题

Hope this helps 希望这可以帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM