InputStream 跳过字节
InputStream skip bytes
我正在使用 TCP 套接字与对等方通信,我看到当我读取第一条传入消息的 inputStream
时,一切顺利。然后,当我读取第二条传入消息的 inputStream
时,inputStream
跳过 第一个 n
字节(n
是不同的每个 运行).
中的正数
我怎么知道 inputStream
跳过 n
字节?使用 Wireshark,我可以看到第二条消息接收良好,但 Java TCP 套接字仍然忽略第一个 n
字节。
此外,Wireshark 本身向我展示了一些奇怪的东西 - 通过查看 Wireshark 中的第一条消息,它在末尾包含:第二条消息的开头。通过查看 Wireshark 中的第二条消息,消息的开头也出现在这里。
我不明白这是怎么回事。
技术细节 + Wireshark 照片:
- 我收到的第一条消息是 'Handshake' 消息。
- 我收到的第二条消息每次都不同,但大部分时间都是 'extended' 消息。
- 我检查了我的代码,但我只在两个地方读到相同的
InputStream
:当我等待 'Handshake' 和当我等待其余消息时不等于 'Handshake' 消息。
我收到的第一条消息:
* 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());
详细信息:13
直到 45
是第一条消息的内容 - Handshake
。 00
直到 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[]
}
详细信息:00
直到 3a
是第二条消息的前 n
个字节。
当我读取 InputStream
时,我得到以下字节:从 6d
到 65
。
为什么 Wireshark 显示相同的数据两次,为什么我的 InputStream
跳过第二条消息的前 n
个字节?
您写道:
I calculate how much to read and I use every byte.
你编码了:
data = new byte[pstrLength + 48];// how much we need to read more.
dataInputStream.read(data);
此代码与您的描述不符。第二个 read()
不能保证填满缓冲区。请参阅Javadoc。将其更改为 readFully()
.
注意 在您的 isPeerConnected
测试中还有另一个问题。您正在读取一个字节的输入并将其丢弃。如果它仍然连接,这将导致您失去与对等点的同步。
我正在使用 TCP 套接字与对等方通信,我看到当我读取第一条传入消息的 inputStream
时,一切顺利。然后,当我读取第二条传入消息的 inputStream
时,inputStream
跳过 第一个 n
字节(n
是不同的每个 运行).
我怎么知道 inputStream
跳过 n
字节?使用 Wireshark,我可以看到第二条消息接收良好,但 Java TCP 套接字仍然忽略第一个 n
字节。
此外,Wireshark 本身向我展示了一些奇怪的东西 - 通过查看 Wireshark 中的第一条消息,它在末尾包含:第二条消息的开头。通过查看 Wireshark 中的第二条消息,消息的开头也出现在这里。
我不明白这是怎么回事。
技术细节 + Wireshark 照片:
- 我收到的第一条消息是 'Handshake' 消息。
- 我收到的第二条消息每次都不同,但大部分时间都是 'extended' 消息。
- 我检查了我的代码,但我只在两个地方读到相同的
InputStream
:当我等待 'Handshake' 和当我等待其余消息时不等于 'Handshake' 消息。
我收到的第一条消息:
* 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());
详细信息:13
直到 45
是第一条消息的内容 - Handshake
。 00
直到 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[]
}
详细信息:00
直到 3a
是第二条消息的前 n
个字节。
当我读取 InputStream
时,我得到以下字节:从 6d
到 65
。
为什么 Wireshark 显示相同的数据两次,为什么我的 InputStream
跳过第二条消息的前 n
个字节?
您写道:
I calculate how much to read and I use every byte.
你编码了:
data = new byte[pstrLength + 48];// how much we need to read more.
dataInputStream.read(data);
此代码与您的描述不符。第二个 read()
不能保证填满缓冲区。请参阅Javadoc。将其更改为 readFully()
.
注意 在您的 isPeerConnected
测试中还有另一个问题。您正在读取一个字节的输入并将其丢弃。如果它仍然连接,这将导致您失去与对等点的同步。