现在有一个C++写的服务器,我要写一个java应用程序和他通信。
每次向服务器发送消息时,都是先发送一个数据包头,指明数据包体的长度和类型,再发送数据包体。class MsgHeader
{
int DataType;
int DataLength;
};也就是说,服务器接受消息时,每次都期望先接受到一个MsgHeader那么长的比特流,解析出DataType和DataLength,然后按照DataLength指明的长度,再接受对应的字节数作为消息体,最后根据DataType做相应的处理。我的问题是,在我的java应用程序中组织好数据包头并发送时,是不是应该用DataOutputStream来发送,应该如何发送呢?
如果不是话,又该怎么办呢?我是java初学者,麻烦大家了,谢谢!
每次向服务器发送消息时,都是先发送一个数据包头,指明数据包体的长度和类型,再发送数据包体。class MsgHeader
{
int DataType;
int DataLength;
};也就是说,服务器接受消息时,每次都期望先接受到一个MsgHeader那么长的比特流,解析出DataType和DataLength,然后按照DataLength指明的长度,再接受对应的字节数作为消息体,最后根据DataType做相应的处理。我的问题是,在我的java应用程序中组织好数据包头并发送时,是不是应该用DataOutputStream来发送,应该如何发送呢?
如果不是话,又该怎么办呢?我是java初学者,麻烦大家了,谢谢!
OutputStream ops = socket.getOutputStream();
OutputStreamWriter opsw = new OutputStreamWriter(ops);
BufferedWriter bw = new BufferedWriter(opsw);
bw.write("你想发送的东东");
bw.flush();
bw.close();
OutputStream ops = socket.getOutputStream();
OutputStreamWriter opsw = new OutputStreamWriter(ops);
BufferedWriter bw = new BufferedWriter(opsw);
bw.write("你想发送的东东");
bw.flush();
bw.close();
writeObject(Object obj)
MsgHeader msgHeader = new MsgHeader();
msgHeader.DataType = 12343;
msgHeader.DataLength = 255;
Socket socket = new Socket("URL", 80);// 地址,端口号
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
try {
//MsgHeader就依次写吧
dos.writeInt(msgHeader.DataType);
dos.writeInt(msgHeader.DataLength);
} finally {
dos.close();
}
private DataOutputStream iob; public MyOutputBuffer() {
ios = new ByteArrayOutputStream();
iob = new DataOutputStream(ios);
} public int Size() {
return ios.size();
} public byte[] ToByteArray() {
return ios.toByteArray();
} public void Reset() {
ios.reset();
} public void Write(byte[] b) throws IOException {
iob.write(b);
} public void Write(byte[] b, int offset, int len) throws IOException {
iob.write(b, offset, len);
} public void WriteLong(long value) throws IOException {
iob.writeLong(value);
} public void WriteInt(int value) throws IOException {
int tmp;
tmp = (value << 24) | ((value << 8) & 0xFF0000) | ((value >> 8) & 0xFF00) | ((value >> 24) & 0xFF);
iob.writeInt(tmp);
} public void WriteUInt32(long value) throws IOException {
int tmp;
tmp = (int) (((value << 24) & 0xFF000000) | ((value << 8) & 0xFF0000) | ((value >> 8) & 0xFF00) | ((value >> 24) & 0xFF));
iob.writeInt(tmp);
} public void WriteShort(int value) throws IOException {
int tmp;
tmp = ((value << 8) & 0xFF00) | ((value >> 8) & 0xFF);
iob.writeShort(tmp);
} public void WriteChar(char value) throws IOException {
int tmp;
tmp = ((value << 8) & 0xFF00) | ((value >> 8) & 0xFF);
iob.writeShort(tmp);
} public void WriteStr(String value) throws IOException {
int len, i;
len = value.length();
WriteInt(len);
for (i = 0; i < len; i++) {
WriteChar(value.charAt(i));
}
if ((len & 1) != 0) {
WriteChar('\0');
}
} public void WriteUTF8(String value) throws IOException {
if (value != null && value.length() > 0) {
byte[] buf = value.getBytes("UTF-8");
this.WriteInt(buf.length);
iob.write(buf);
} else {
if (value != null)
this.WriteInt(0);
else
this.WriteInt(-1);
}
} public void close() {
try {
ios.close();
iob.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}可以这样使用:
//构建消息体(例如)
JMGSOutputBuffer ob = new JMGSOutputBuffer();
ob.WriteInt(15);//消息类型
ob.WriteInt(50);//消息长度
byte[] bs = ob.ToByteArray(); //获取字节数组
ob.close();//发送数据....
所以你的问题是怎么发数据。至于怎么发数据,DataOutputStream只不过是封装了一下,提供了 writeInt, writeBoolean等一系列接口,本质上,还是 write(byte[]).这个实际上,就是一个序列化问题,就看你们之间的协议是怎么定的了。注意C++的程序有字节序的问题,所以不要迷信 DataOutoutStream 的 writeInt接口,可能对端的C++程序会解码错误。所以,协议!协议!还是协议! 你两个程序之间的协议要确定到每个字节序!所以才叫, 序列化 问题。
谢谢您的回复,我想问一下。
我用ObjectOutputStream把一个MsgHeader对象写到一个byte数组中之后,发现数组的大小是62,这是为什么呢?
谢谢,刚才才知道,JVM是大端序的,而我写的C++服务器所用的CPU是小端序的,呵呵~