Spring 将ByteArraylengHeaderSerializer与java.net.Socket客户端一起使用

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

我正在尝试使用ByteArrayLengthHeaderSerializer将一个简单的java.net.Socket TCP客户端连接到Spring集成TCP服务器

以下是相关的客户端代码片段:

    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字节),后跟
字节[]

我更新了问题-我解决了第一个问题。在这个例子中,我只是使用了一个字符串。实际上,服务器将序列化和反序列化不同大小的不同消息类型。您不显示channel
toTcp
的使用者,但不应在send方法中操作数据。如果使用者是带序列化程序的出站通道适配器,则该序列化程序将为您添加长度标头。对象输入流需要一个幻数,指示这是一个java序列化对象。适配器正在添加长度标头。正如我所说的,如果要使用java序列化,应该在服务器端使用这些(反)序列化程序,而不是长度头实现。Jave序列化有自己的机制来划分对象。