Java - 从套接字通道读取

Posted

技术标签:

【中文标题】Java - 从套接字通道读取【英文标题】:Java - Reading from a socketchannel 【发布时间】:2016-12-15 10:24:36 【问题描述】:

所以我在 java 中使用 SocketChannels 来发送和接收项目的数据。该项目与需要数据的 ByteBuffer 的第 3 方交互,但其前缀为 4 个字节,即其​​长度。

接收时我会收到一个 ByteBuffer,我需要从前面解构 4 字节长度并提取数据。我收到的消息不是固定长度的。

我目前的实现如下:

public PedResponse send(ByteBuffer message) 
        String returnString;
        try 

            message.flip();

            while (message.hasRemaining()) 
                socketChannel.write(message);
            

            ByteBuffer readBuffer = ByteBuffer.allocate(5000);
            int bufferSize = socketChannel.read(readBuffer);
            if (bufferSize == -1) 
                socketChannel.close();
             else 
                readBuffer.flip();
            

            returnString = new String(deconstructMessage(readBuffer.array()), "UTF-8").trim();

            response = parser.parseResponse(returnString);

         catch (IOException e) 
            e.printStackTrace();
        
        return response;
    

private ByteBuffer constructMessage(byte[] data) 

        // Construct a buffer where we'll put the data to send
        ByteBuffer sendBuffer = ByteBuffer.allocate(4 + data.length);

        // it's the default, but included for clarity
        sendBuffer.order(ByteOrder.BIG_ENDIAN);

        // Put the 4-byte length, then the data
        sendBuffer.putInt(data.length);
        sendBuffer.put(data);

        // Extract the actual bytes from our sendBuffer
        return sendBuffer;
     

public byte[] deconstructMessage(byte[] data) 

        byte[] filteredByteArray = Arrays.copyOfRange(data, 4, data.length - 4);

        return filteredByteArray;
    

//Currently not being used.
private byte[] deconstructMessage(byte[] data) 

        // Construct a buffer where we'll put the data to send
        ByteBuffer receiveBuffer = ByteBuffer.allocate(data.length);

        // it's the default, but included for clarity
        receiveBuffer.order(ByteOrder.BIG_ENDIAN);

        // Get the 4-byte length, then the data
        receiveBuffer.getInt(data.length);
        receiveBuffer.get(data);

        // Extract the actual bytes from our receivedBuffer
        byte[] dataReceived = receiveBuffer.array();
        return dataReceived;
    

如您所见,我正在创建一个大小为 5000 的新 ByteBuffer,但理想情况下我不想这样做。所以我的问题是,我怎样才能不使用这个超大的 ByteBuffer,而只是读取我收到的数据,这样我就可以使用我未使用的解构消息方法?

【问题讨论】:

【参考方案1】:

ByteBuffer 有method get(),它从当前位置返回字节。 所以,你可以先读取 4 个字节,然后得到大小。

【讨论】:

所以在 send 方法中,我创建了一个名为 readBuffer 的新 ByteBuffer。所以理想情况下,我想摆脱它。我最好的选择是什么 据我所知,ByteBuffer 中没有 unwrap() 方法。无论如何,您需要自己的 byte[] 从缓冲区复制数据 而不是 5000 你可以使用方法 remaining() 对不起,对此有点困惑,所以我猜我需要做这样的事情:??字节缓冲区缓冲区=空;缓冲区.位置(0);缓冲区.limit(1); while (buffer.hasRemaining()) socketChannel.read(buffer); buffer.rewind(); ***.com/questions/1396016/… ...查看此链接可能会对您有所帮助

以上是关于Java - 从套接字通道读取的主要内容,如果未能解决你的问题,请参考以下文章

从 Java NIO socketchannel 读取字节,直到到达标记

java.nio.channels的通道定义

如何使用套接字通道读取和写入数据并接受连接

数据报通道套接字不写 Java

JAVA NIO 之Channel

JAVA NIOChannel通道