请教各位java大神一个问题,不胜感激~~~~~~~

时间:2022-09-30 21:56:55
本人是写C++的,不过我们项目需要用到一些java技术,java也是略懂皮毛,底层的一些API方法了解的比较少。
说下问题吧,我现在想用java去做一个基于TCP通讯的客户端,服务端是C++实现的,我们通讯的数据包是自己定义的私有格式,
因为C++有指针可以用,所以封包解包都是小菜菜。现在想用java来实现打包解包的操作。
我的私有包头是这样定义的:
public class HeaderStruct {
public int length;
public int seq;
public byte[] src_type = new byte[1];
public byte[] terminal = new byte[20];
public int to_flow;
public byte[] msg_type = new byte[1];
public int msgid;
}
那么这个包头总共是38字节,包头之后拼接数据,数据是String类型的。
现在需要把数据拼装好然后调用socket的接口将数据发送出去,过程就这样。
解包的话也是从包头开始解,比如第一个先解出4字节的数据,表示长度,然后偏移4字节解出seq,一次类推。
因为java里面没有指针,所以对内存操作起来很费劲,我也不知道能不能进行内存拷贝,我试着写了一些代码,但发现完全不行,也可能是我的用法不对吧,如下:
public class pack {

public byte[] PackHeader(HeaderStruct hs)
{
byte[] header = new byte[38];
//byte[] bt = ByteBuffer.allocate(4).putInt(hs.length).array();
//byte[] bt2 = intToByteArray(hs.length);
System.arraycopy(header, 0, ByteBuffer.allocate(4).putInt(hs.length).array(), 0, 4);
System.arraycopy(header, 3, ByteBuffer.allocate(4).putInt(hs.seq).array(), 0, 4);
System.arraycopy(header, 7, hs.src_type, 0, 1);
System.arraycopy(header, 8, hs.terminal, 0, 20);
System.arraycopy(header, 28, ByteBuffer.allocate(4).putInt(hs.to_flow).array(), 0, 4);
System.arraycopy(header, 32, hs.msg_type, 0, 1);
System.arraycopy(header, 33, ByteBuffer.allocate(4).putInt(hs.msgid).array(), 0, 4);
return header;
}

private byte[] intToByteArray (final int integer) {
int byteNum = (40 - Integer.numberOfLeadingZeros (integer < 0 ? ~integer : integer)) / 8;
byte[] byteArray = new byte[4];

for (int n = 0; n < byteNum; n++)
byteArray[3 - n] = (byte) (integer >>> (n * 8));

return (byteArray);
}

public static void main(String[] args)
{
pack pk = new pack();
HeaderStruct hs = new HeaderStruct();
hs.length = 100;
hs.seq = 1;
hs.msgid = 1001;
byte[] header = pk.PackHeader(hs);

for(byte t : header)
{
System.out.format("0X%x\n", t);
}
}
}
打印出来全是0

5 个解决方案

#1


System.arraycopy 是我把这个方法的参数搞反了,调换一下位置就OK了

C里面的copy函数都是被拷贝的值都是放在后面的,没想到JAVA是放前面,坑爹啊 请教各位java大神一个问题,不胜感激~~~~~~~

#2


引用 1 楼 llg521208 的回复:
System.arraycopy 是我把这个方法的参数搞反了,调换一下位置就OK了

C里面的copy函数都是被拷贝的值都是放在后面的,没想到JAVA是放前面,坑爹啊 请教各位java大神一个问题,不胜感激~~~~~~~

不需要copy来copy去的。稍等会吧,我发段代码给你

#3


自定义数据包,无论自定义为何种结构。最终进行通信时,无非就是字节数据的传递。只在客户只需要将对应数据进行编码转为对应的byte数组,最终传递给服务端,由服务端进行解码操作。这点相信楼主也很清楚了。客户端编码这块,楼主可以参考下以下代码,有疑问可以追问。

import com.sun.xml.internal.ws.api.message.Packet;

import java.nio.ByteBuffer;

/**
 * @author zhuangqing
 */
public class DataEncodeTest {

    public static void main(String[] args) {
        DataPacket packet = new DataPacket();
        packet.header = new HeaderStruct();
        packet.data = "test";
        //最终要发送给服务端的数据
        byte[] sendData = packet.toBytes();
        System.out.println(sendData.length);
    }
}

/**
 * 协议包
 */
class DataPacket {
    public HeaderStruct header;
    public String data;

    public byte[] toBytes() {
        byte[] strData = data.getBytes();
        int dataSize = HeaderStruct.DATA_SIZE + 4 + strData.length;
        ByteBuffer buffer = ByteBuffer.allocate(dataSize);
        buffer.put(header.toBytes());
        buffer.putInt(strData.length);
        buffer.put(strData);
        return buffer.array();
    }
}

/**
 * 包头描述
 */
class HeaderStruct {
    public int length;
    public int seq;
    public byte[] src_type = new byte[1];
    public byte[] terminal = new byte[20];
    public int to_flow;
    public byte[] msg_type = new byte[1];
    public int msgid;
    /**
     *  4(length)+4(seq)+4(一个int值存src_type.length)+1(src_type all data) + ... + 4(msgid)
     *  共7个int + 1b + 20b + 1b
     */
    public static final int DATA_SIZE = 7 * 4 + 1 + 20 + 1;

    public byte[] toBytes() {
        ByteBuffer buffer = ByteBuffer.allocate(HeaderStruct.DATA_SIZE);
        buffer.putInt(length);
        buffer.putInt(seq);
        buffer.putInt(src_type.length);
        buffer.put(src_type);
        buffer.putInt(terminal.length);
        buffer.put(terminal);
        buffer.putInt(to_flow);
        buffer.putInt(msg_type.length);
        buffer.put(msg_type);
        buffer.putInt(msgid);
        return buffer.array();
    }
}

#4


JAVA也有字符串定位和位移的
JAVA里只是不能显示地使用指针而已,但根据地址操作无处不在。

#5


自己写代码打包解包有点麻烦,我最近也在做TCP,可以加扣交流下的

#1


System.arraycopy 是我把这个方法的参数搞反了,调换一下位置就OK了

C里面的copy函数都是被拷贝的值都是放在后面的,没想到JAVA是放前面,坑爹啊 请教各位java大神一个问题,不胜感激~~~~~~~

#2


引用 1 楼 llg521208 的回复:
System.arraycopy 是我把这个方法的参数搞反了,调换一下位置就OK了

C里面的copy函数都是被拷贝的值都是放在后面的,没想到JAVA是放前面,坑爹啊 请教各位java大神一个问题,不胜感激~~~~~~~

不需要copy来copy去的。稍等会吧,我发段代码给你

#3


自定义数据包,无论自定义为何种结构。最终进行通信时,无非就是字节数据的传递。只在客户只需要将对应数据进行编码转为对应的byte数组,最终传递给服务端,由服务端进行解码操作。这点相信楼主也很清楚了。客户端编码这块,楼主可以参考下以下代码,有疑问可以追问。

import com.sun.xml.internal.ws.api.message.Packet;

import java.nio.ByteBuffer;

/**
 * @author zhuangqing
 */
public class DataEncodeTest {

    public static void main(String[] args) {
        DataPacket packet = new DataPacket();
        packet.header = new HeaderStruct();
        packet.data = "test";
        //最终要发送给服务端的数据
        byte[] sendData = packet.toBytes();
        System.out.println(sendData.length);
    }
}

/**
 * 协议包
 */
class DataPacket {
    public HeaderStruct header;
    public String data;

    public byte[] toBytes() {
        byte[] strData = data.getBytes();
        int dataSize = HeaderStruct.DATA_SIZE + 4 + strData.length;
        ByteBuffer buffer = ByteBuffer.allocate(dataSize);
        buffer.put(header.toBytes());
        buffer.putInt(strData.length);
        buffer.put(strData);
        return buffer.array();
    }
}

/**
 * 包头描述
 */
class HeaderStruct {
    public int length;
    public int seq;
    public byte[] src_type = new byte[1];
    public byte[] terminal = new byte[20];
    public int to_flow;
    public byte[] msg_type = new byte[1];
    public int msgid;
    /**
     *  4(length)+4(seq)+4(一个int值存src_type.length)+1(src_type all data) + ... + 4(msgid)
     *  共7个int + 1b + 20b + 1b
     */
    public static final int DATA_SIZE = 7 * 4 + 1 + 20 + 1;

    public byte[] toBytes() {
        ByteBuffer buffer = ByteBuffer.allocate(HeaderStruct.DATA_SIZE);
        buffer.putInt(length);
        buffer.putInt(seq);
        buffer.putInt(src_type.length);
        buffer.put(src_type);
        buffer.putInt(terminal.length);
        buffer.put(terminal);
        buffer.putInt(to_flow);
        buffer.putInt(msg_type.length);
        buffer.put(msg_type);
        buffer.putInt(msgid);
        return buffer.array();
    }
}

#4


JAVA也有字符串定位和位移的
JAVA里只是不能显示地使用指针而已,但根据地址操作无处不在。

#5


自己写代码打包解包有点麻烦,我最近也在做TCP,可以加扣交流下的