java 套接字编程新手!我正在尽力理解java套接字编程,以及如何解码像数据包一样的“C”strut。
客户端是python,它在标签之间发送数据包,
示例有效负载:<tag1> data packet 1</tag1><tag2>data packet 2</tag2>
有一个c代码来接收有效负载并用结构解码有效负载,所有标签都是30字节,数据包1,2,..n将具有不同的结构
我对java程序相当陌生,在通过网络搜索后,我可以编写一个从客户端接收有效负载的套接字服务器,现在面临解码数据包的问题。 我可以显示字节。所以使用Arrays.copyOfRange方法来获取数据。
数据包数据如下所示,
typedef struct {
unsigned char dataType;
unsigned char value[4];
} GEN_VAL
typedef struct {
unsigned char dataType;
unsigned char numBytes;
unsigned char value[32];
} GEN_STR_32;
typedef struct {
char startTag[32];
GEN_STR_32 c_code;
GEN_STR_32 c_name;
GEN_STR_32 c_info;
GEN_VAL i_type;
GEN_VAL i_count1;
GEN_VAL i_count2;
char endTag[32];
} DATA_PACKET_1;
我收到带有以下代码片段的缓冲区
DataInputStream inStream = new DataInputStream
(new BufferedInputStream(socket.getInputStream()));
while ( ( noOfBytes = (int)inStream.read(recvBuff)) != -1)
{
cDecode mydecode = new cDecode();
mydecode.decodePacket(noOfBytes, recvBuff);
}
cDecode.java
public void decodePacket(int TotalBytes, byte[] BuffRecv)
{
byte[] GetTag = new byte[32];
byte[] GEN_STR_32 = new byte[32];
byte[] GEN_INT_4 = new byte[4];
GetTag = Arrays.copyOfRange(BuffRecv,0,31);
String TagStr = new String(GetTag).trim(); //get start tag
int startloc = 31;
int offset = startloc + 32;
GEN_STR_32 = Arrays.copyOfRange(Buff,startloc,offset);
String cCode = new String(GEN_STR_32).trim(); // get value of cCode
System.out.println("Code :" + cCode );
startloc = offset;
offset = startloc + 32;
GEN_STR_32 = Arrays.copyOfRange(Buff,startloc,offset);
String cName = new String(GEN_STR_32).trim(); //get value of cName
System.out.println("Name:" + cName );
startloc = offset;
offset = startloc + 32;
GEN_STR_32 = Arrays.copyOfRange(Buff,startloc,offset);
String cInfo = new String(GEN_STR_32).trim(); //get value of cName
System.out.println("Info:" + cInfo );
startloc = offset;
offset = offset + 4;
ByteBuffer iTypeByteBuff = ByteBuffer.wrap(GEN_DATA_INT_4);
int iType= iTypeByteBuff .getInt();
System.out.println("type :" + iType);
startloc = offset;
offset = offset + 4;
// likewise used ByteBuffer for remaining integer data
// for receiving end tag, offset is added with 32!
}
前 3 个数据是字符串值并且
第二个 3 数据具有整数值
字符串值显示正确。
在将字节转换为整数时发现问题,不确定我是否在 Arrays.copyOfRange 方法中使用正确的 startloc 和 offset 值。
我根据从网上得到的信息尝试了这个。
我还了解到有一个单独的类,没有适用于所有数据结构的方法。但我找不到任何完整的例子,因为“sizeof”在java中不可用。
有人可以指导我在这种情况下解码数据包的正确方法吗?
最佳答案
对于字节数组或输入/输出,您可以使用 ByteBuffer。
byte[] bytes = ...
ByteBuffer buf = ByteBuffer.wrap(bytes);
buf.order(ByteOrder.LITTLE_ENDIAN); // Intel byte order.
short sh = buf.getShort(sh); // Java short = 2B
int unsignedSh = buf.getShort() & 0xFFFF; // Unsigned short emulation
ByteBuffer buf = ByteBuffer.allocate(4);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putShort(sh); // Java short = 2B
buf.putShort((short) unsignedSh);
还有一个二进制格式标准ASN,可以像更多语法一样工作,但在这种情况下,上面的就可以了。
C端的一个问题是领域对齐和平台可移植性。人们可以使用宏将结构转换为完全指定的二进制数据结构构建调用。
<小时/>评论后,使用 DataInputStream
您似乎没有使用 DataInputStream 的数据特定读取调用。
enum DataType {
X0,
GEN_VAL,
X2,
X3,
GEN_STR_32,
...
}
class GenStr32 {
final DataType dataType = DataType.GEN_STR_32;
int numbytes; // 0..255
String value; // 32 bytes incl. '\0' in C
}
void readAnyTyped(DataInputStream in) {
int dataTypeIx = in.readByte() & 0xFF;
DataType dataType = DataType.values()[dataTypeIx];
switch (dataType) {
case GEN_STR_32:
GenStr32 data = new GenStr32();
data.numbytes = in.readByte();
byte[] bytes = new byte[data.numbytes]; // or 32?
bytes = in.readFully();
int length = 0;
while (length < bytes.length && bytes[length] != 0) {
++length;
}
data.value = new String(bytes, 0, length,
StandardCharsets.ISO_8859_1);
process(data);
break;
}
}
DataInputStream 可能更直接。 ByteBuffer 的优点是可指定字节顺序,因为 java 默认为 BIG_ENDIAN。
关于java - 如何使用java套接字编程解码C结构(如数据包),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31317196/