如何在Java中生成用于通过网络发送数据的字节数组
我正在尝试连接到PostgreSQL服务器(实现wire协议),但我不知道如何动态生成字节数组的消息帧。例如,在下面的代码中,我做了很多System.arraycopy
调用来将所有生成的字节推送到一个单字节数组中,似乎有更好的方法
import java.io.*;
import java.net.Socket;
import java.nio.ByteBuffer;
public class Connection {
public void connect(String hostName, int port) {
try {
Socket dbSocket = new Socket(hostName, port);
DataOutputStream dOut = new DataOutputStream(dbSocket.getOutputStream());
byte[] message = buildStartupMessage("sa");
dOut.write(message);
DataInputStream dIn = new DataInputStream(dbSocket.getInputStream());
byte bytes;
while((bytes = dIn.readByte()) != 0) {
System.out.println(bytes);
}
} catch(Exception e) {
System.out.println("Got an exception");
}
}
public byte[] buildStartupMessage(String username) {
// Postgres startup message format:
// 32 bit length
// 32 bit protocol
// string name
// null byte
// string value
// null byte
byte nullbyte = 0;
byte[] valbytes = username.getBytes();
byte[] namebytes = "user".getBytes();
System.out.println("number of bytes for sa is: " + valbytes.length);
int length = 4 + 4 + valbytes.length + namebytes.length + 2;
byte[] lengthbytes = ByteBuffer.allocate(4).putInt(length).array();
byte[] protocolbytes = ByteBuffer.allocate(4).putInt(3).array();
byte[] startupmessage = new byte[length];
int currIndex = 0;
System.arraycopy(lengthbytes, 0, startupmessage, currIndex, lengthbytes.length);
currIndex += lengthbytes.length;
System.arraycopy(protocolbytes, 0, startupmessage, currIndex, protocolbytes.length);
currIndex += protocolbytes.length;
System.arraycopy(namebytes, 0, startupmessage, currIndex, namebytes.length);
currIndex += namebytes.length;
startupmessage[currIndex] = nullbyte;
currIndex++;
System.arraycopy(valbytes, 0, startupmessage, currIndex, valbytes.length);
currIndex += valbytes.length;
startupmessage[currIndex] = nullbyte;
return startupmessage;
}
public static void main(String[] args) {
Connection conn = new Connection();
conn.connect("localhost", 5432);
}
}
# 1 楼答案
不要。使用
DataOutputStream
的原语直接编写您想要的内容。例如:。。。根据协议,当通过
DataInputStream
读取时,情况正好相反。将缓冲流放在数据流下以保存系统调用但是。。。这里真正的问题是“为什么”?您当然应该使用PostgresSQL JDBC驱动程序与服务器进行通信,而不是自己尝试滚动整个协议。供应商已经为您完成了。不要这样做
注意:当您遇到异常时,不要打印出
Got an exception.
这太愚蠢了。打印异常# 2 楼答案
试试这个