Spring 将ByteArraylengHeaderSerializer与java.net.Socket客户端一起使用
我正在尝试使用ByteArrayLengthHeaderSerializer将一个简单的java.net.Socket TCP客户端连接到Spring集成TCP服务器 以下是相关的客户端代码片段:Spring 将ByteArraylengHeaderSerializer与java.net.Socket客户端一起使用,spring,spring-integration,Spring,Spring Integration,我正在尝试使用ByteArrayLengthHeaderSerializer将一个简单的java.net.Socket TCP客户端连接到Spring集成TCP服务器 以下是相关的客户端代码片段: Socket socket = null; OutputStream out = null; InputStream in = null; try { socket = new Socket(host, port); out = n
Socket socket = null;
OutputStream out = null;
InputStream in = null;
try {
socket = new Socket(host, port);
out = new BufferedOutputStream(socket.getOutputStream());
in = new BufferedInputStream(socket.getInputStream());
byte[] lengthBuf = new byte[4];
int size = in.read(lengthBuf, 0, lengthBuf.length);
ByteArrayInputStream bis = new ByteArrayInputStream(lengthBuf);
ObjectInputStream ois = new ObjectInputStream(bis);
int dataSize = ois.readInt();
System.out.println("Got size: " + dataSize);
byte[] dataBuffer = new byte[dataSize];
int dataRead = in.read(dataBuffer, 0, dataBuffer.length);
bis = new ByteArrayInputStream(dataBuffer);
ois = new ObjectInputStream(bis);
String data = (String) ois.readObject();
System.out.println("read " + dataRead + " bytes, got data: " + data);
以下是服务器端配置:
@MessagingGateway(defaultRequestChannel="toTcp")
public interface Gateway {
void send(@Payload byte[] data, @Header(IpHeaders.CONNECTION_ID) String connectionId);
}
@Bean
public AbstractServerConnectionFactory serverFactory() {
AbstractServerConnectionFactory connectionFactory = new TcpNetServerConnectionFactory(port);
ByteArrayLengthHeaderSerializer serDeser = new ByteArrayLengthHeaderSerializer();
connectionFactory.setSerializer(serDeser);
connectionFactory.setDeserializer(serDeser);
return connectionFactory;
}
@Bean
public TcpReceivingChannelAdapter inboundAdapter(AbstractServerConnectionFactory connectionFactory) {
TcpReceivingChannelAdapter inbound = new TcpReceivingChannelAdapter();
inbound.setConnectionFactory(connectionFactory);
inbound.setOutputChannel(fromTcp());
return inbound;
}
以及呼叫代码:
public void send(String data, String header) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
System.out.println("data.length is " + data.length());
oos.writeObject(data);
byte[] bytes = bos.toByteArray();
gateway.send(bytes, header);
}
}
当我发送数据(例如“abc”)时,我(在客户端)收到以下错误:
无效流头:0000000 a
在服务器端,我得到:
SoftEndOfStreamException: Stream closed between payloads
我做错了什么?否-一个
ObjectOutputStream
序列化java对象(并且输入流反序列化)。您不需要长度头反序列化程序,只需使用DefaultSerializer
和DefaultDeserializer
(来自Spring Core),而不添加头
您将收到错误,因为序列化在开始时添加了更多内容
或者,如果您只发送字符串,可以使用
String.getBytes()
发送长度(4字节),后跟字节[]
我更新了问题-我解决了第一个问题。在这个例子中,我只是使用了一个字符串。实际上,服务器将序列化和反序列化不同大小的不同消息类型。您不显示channeltoTcp
的使用者,但不应在send方法中操作数据。如果使用者是带序列化程序的出站通道适配器,则该序列化程序将为您添加长度标头。对象输入流需要一个幻数,指示这是一个java序列化对象。适配器正在添加长度标头。正如我所说的,如果要使用java序列化,应该在服务器端使用这些(反)序列化程序,而不是长度头实现。Jave序列化有自己的机制来划分对象。