如何格式化 TCP header 值并推送到字节数组以在 Java 中进行数据包测试

How to format TCP header values and push to a byte array for packet test in Java

我想弄清楚如何将一些手动创建的 TCP header 数据推送到字节数组。我将能够使用 JnetPcap.send(byte[] packet) 并使用 wireshark 查看它,我现在需要的是将数据包创建为字节数组,以便我可以将其发送。我想手动执行此操作,因为有很多库函数可以用来创建 header.

我根本找不到任何关于如何格式化值或将它们加载到数组的解释。我也不确定我使用的值是否有效。这就是我正在考虑使用的...

public static int sourcePort = 1234; //16 bits
public static int destinationPort = 80; //16 bits
public static int sequenceNum = 0; //32 bits - Can this be arbitrary?
public static int ackNum = 0; //32 bits - sequenceNumber + next data start
public static int dataOffset = 5; //4 bits - Minimum value of 5
public static int reserved = 0; //4 bits - Always 0
public static int controlFlags = 0; //8 bits - Not sure if I need any
public static int windowSize = 0; //16 bits Can this be arbitrary?
public static int checkSum = 0; //16 bits - ?use TCP.calculateChecksum() 
public static int urgent = 0; //16 bits

byte[] packet = new byte[160];
//Now load the values into the byte[]

(我也在使用内置的获取以太网和获取 Ipv header 函数的 JnetPcap)

更新: 我发现这个片段看起来像是我需要将十六进制值放入字节数组的实用程序:

byte[] pktBytes = FormatUtils.toByteArray("0015c672234c90e6ba92661608004500002d358c4000800600000a000b050a090028c26e270fb8b256e3a2009f785018faf01f550000746573740a");
JMemoryPacket packet = new JMemoryPacket(pktBytes);

那么,我该如何将我的价值观转化为此处。会不会是字面上的十六进制翻译附加在一起?

所以我的 16 位 destinationPort = 80;变为 0050 ... 并且 32 位 sequenceNum = 0;变为 0000 0000 ... 4 位 dataOffset = 5;变成5了,好像可以,我试试看

(它们有 118 个十六进制数字,对 TCP header 来说是正确的吗?我的值会留下 40 个十六进制数字,也许它们有有效负载或 IP/Ethernet header 作为好吗?)

通常的方法是通过 ByteArrayOutputStream 包裹在 DataOutputStream.

我发现我可以使用 jNetPcap 函数来加载 header:

Tcp tcp = packet.getHeader(new Tcp());  
tcp.source(sourcePort);  
tcp.destination(destinationPort); 
tcp.seq(sequenceNum);
tcp.ack(ackNum);
tcp.hlen(dataOffset);
tcp.flags(controlFlags);
tcp.window(windowSize);       
tcp.checksum(tcp.calculateChecksum()); 
tcp.urgent(urgent);

这对我有用,但我也可以手动设置字节数组并将整个数组和完整的 2-3-4 层 header 传递给发送函数。