我正在使用TCP套接字与对等方进行通信,我看到当我为第一条传入消息读取inputStream
时,一切顺利。然后当我为第二个传入消息阅读inputStream
时,inputStream
跳过,第一个n
字节(n
是一个不同的正数每次运行。)
我怎么知道inputStream
跳过n
个字节?使用Wireshark,我可以看到第二条消息收到的很好,但Java TCP套接字仍然忽略了第一个n
字节。
此外,Wireshark本身向我展示了一些奇怪的东西 - 通过查看Wireshark中的第一条消息,它最后包含:第二条消息的开头。通过查看Wireshark中的第二条消息,此处也会显示消息的开头。
我无法理解发生了什么。
技术细节+ Wireshark照片:
InputStream
:当我在等待'握手'时,我在等待其余的信息不等于' 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
字节?
答案 0 :(得分:1)
您写道:
我计算读取的数量,并使用每个字节。
您编码:
data = new byte[pstrLength + 48];// how much we need to read more.
dataInputStream.read(data);
此代码与您的说明不符。第二个read()
无法保证填充缓冲区。见Javadoc。将其更改为readFully()
。
注意您的isPeerConnected
测试中还有另一个问题。您正在读取一个输入字节并将其丢弃。如果仍然连接,这将导致您与对等方失去同步。