InputStream跳过字节

时间:2018-02-09 23:56:31

标签: java sockets tcp wireshark bittorrent

我正在使用TCP套接字与对等方进行通信,我看到当我为第一条传入消息读取inputStream时,一切顺利。然后当我为第二个传入消息阅读inputStream时,inputStream 跳过,第一个n字节(n是一个不同的正数每次运行。)

我怎么知道inputStream跳过n个字节?使用Wireshark,我可以看到第二条消息收到的很好,但Java TCP套接字仍然忽略了第一个n字节。

此外,Wireshark本身向我展示了一些奇怪的东西 - 通过查看Wireshark中的第一条消息,它最后包含:第二条消息的开头。通过查看Wireshark中的第二条消息,此处也会显示消息的开头。

我无法理解发生了什么。

技术细节+ Wireshark照片:

  1. 我收到的第一条消息是“握手”消息。
  2. 我收到的第二条消息每次都不同,但大部分时间都是“扩展”消息。
  3. 我检查了我的代码,我只在两个地方读了同一个InputStream:当我在等待'握手'时,我在等待其余的信息不等于' Handshake'消息。
  4. 我收到的第一条消息:

     * Offset       Size            Name        value
     * 0            8-bit           byte        pstrLength
     * 1            pstrlen-bit     bytes       pstr
     * 1+pstrlen    64-bit          byte        reserved
     * 9+pstrlen    20-bit          String      torrentInfoHash
     * 29+pstrlen   20-bit          String      peerId
     * 49+pstrlen
    public HandShake(InputStream dataInputStream) throws IOException {
        byte[] data = new byte[1];
        dataInputStream.read(data);
        byte pstrLength = ByteBuffer.wrap(data).get();
        data = new byte[pstrLength + 48];// how much we need to read more.
        dataInputStream.read(data);
    
        ByteBuffer byteBuffer = ByteBuffer.allocate(1 + pstrLength + 48);
        byteBuffer.put(pstrLength);
        byteBuffer.put(data);
        HandShake handShake = HandShake.createObjectFromPacket(byteBuffer.array());
    

    enter image description here

    详细信息:13直到45是第一封邮件的内容 - Handshake00直到3a是第二条消息的第一个n字节,这些字节也将出现在此处:

    我收到的第二条消息:

    public static PeerMessage create(Peer from, Peer to, InputStream inputStream) throws IOException {
        byte[] data = new byte[4];
        boolean isPeerClosedConnection = (inputStream.read(data) == -1);
        if (isPeerClosedConnection)
            throw new IOException("the peer closed the socket:" + from.toString());
        int lengthOfTheRest = ByteBuffer.wrap(data).getInt(); // how much do we need to read more
        data = new byte[lengthOfTheRest];
    
        isPeerClosedConnection = (inputStream.read(data) == -1);
        if (isPeerClosedConnection)
            throw new IOException("the peer closed the socket:" + from.toString());
    
        ByteBuffer byteBuffer = ByteBuffer.allocate(4 + lengthOfTheRest);;
        byteBuffer.putInt(lengthOfTheRest);
        byteBuffer.put(data);
    
        return create(from, to, byteBuffer.array()); // initialize message object from byte[]
    }
    

    enter image description here

    详细信息:00直到3a是第二条消息的第一个n字节。

    当我阅读InputStream时,我会得到以下字节:从6d65

    为什么Wireshark会显示两次相同的数据,为什么我的InputStream会跳过第二条消息的第一个n字节?

1 个答案:

答案 0 :(得分:1)

您写道:

  

我计算读取的数量,并使用每个字节。

您编码:

data = new byte[pstrLength + 48];// how much we need to read more.
dataInputStream.read(data);

此代码与您的说明不符。第二个read()无法保证填充缓冲区。见Javadoc。将其更改为readFully()

注意您的isPeerConnected测试中还有另一个问题。您正在读取一个输入字节并将其丢弃。如果仍然连接,这将导致您与对等方失去同步。