向对等方发送消息的方法:
public static void writeLineToPeer(Peer peer, String message) throws IOException
{
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(peer.getSocket().getOutputStream(), StandardCharsets.UTF_8));
writer.write(message + "\n");
writer.flush();
}
阅读回复:
public class PeersResponse extends Response<Peer>
{
public PeersResponse(InputStream stream) throws InvalidMessageException, IOException
{
super(stream);
parseResponse();
getNextElement();
}
@Override
protected void parseResponse() throws InvalidMessageException, IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(this.stream, "UTF-8"));
setVersion(reader.readLine());
setAmount(reader.readLine());
//Fine until here
}
@Override
public Peer getNextElement() throws InvalidMessageException, IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(this.stream, "UTF-8"));
String ip = reader.readLine();
//Socket exception: Socket is closed
if (NetworkHelper.isValidIPAddress(ip))
{
throw new InvalidMessageException();
}
String port = reader.readLine();
String typeOfPeer = reader.readLine();
if (typeOfPeer.length() != 1)
{
throw new InvalidMessageException();
}
try
{
return PeerFactory.getPeer(typeOfPeer.charAt(0), ip, Integer.parseInt(port));
}
catch (Exception ex)
{
throw new InvalidMessageException(ex);
}
}
}
如您所见,我得到了一个Socket异常:当尝试从具有相同InputStream的BufferedReader的另一个实例读取时,Socket关闭。
正在发送的消息很好,适合此类的结构。
这是什么原因?我该怎么解决这个问题?
第一次在parseResponse()
内部调用read. ReadLine()
时,BufferedReader
从流中读取一大块数据。它读取的不仅仅是一行,因为它还不知道行尾在哪里。它从套接字中读取(和删除)一行的唯一方法是逐个读取字符,并在看到新行时停止。但这将首先破坏使用BufferedReader
的目的。
第二次在parseResponse()
内部调用read. ReadLine()
时,它根本不会从底层套接字读取。它只是解析已经存储在BufferedReader
中的数据并返回下一行。
在parseResponse()
退出时,仍然有数据存储在BufferedReader
中。当读取器变量超出范围时,该数据将丢失。它无法从套接字中读取,因为它已经从套接字中读取。
TLDR;您可以在调试器中单步执行parseResponse()
并查看读取器
实例(检查JDK的内部数据结构)。您将在那里看到整个消息。当parseResponse()
返回时,您将看到消息的其余部分是如何丢失的。