java - 从其InputStream读取后,套接字关闭

标签 java sockets java-stream

向对等体发送消息的方法:

    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异常:尝试从Socket的另一个实例读取时,Socket已关闭
具有相同InputStream的BufferedReader。
发送的消息很好,并且适合此类的结构。
这是什么原因造成的?我怎样才能解决这个问题?

最佳答案

第一次在reader.ReadLine()内部调用parseResponse()时,BufferedReader 会从流中读取大量数据。它读取的不仅仅是一行,因为它尚不知道行尾在哪里。它从套接字读取(或删除)一行的唯一方法是逐个读取字符并在看到新行时停止。但这首先会破坏使用BufferedReader 的目的。
第二次在reader.ReadLine()内部调用parseResponse()时,它根本不会从基础套接字读取。它只是解析已经存储在BufferedReader 中的数据并返回下一行。
parseResponse()退出时,仍然在BufferedReader内部存储了数据。当阅读器变量超出范围时,该数据将丢失。无法从套接字读取它,因为已经从套接字读取了它。
TLDR;
您可以在调试器中逐步浏览parseResponse(),然后在 reader 实例内查看(检查JDK的内部数据结构)。您将在那里看到您的整个消息。并且您将看到parseResponse()返回时,消息的其余部分如何丢失。

关于java - 从其InputStream读取后,套接字关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64249665/

相关文章:

java - 收到的 UDP 消息长度不正确

java - 将对象列表转换为 map

java - 如何通过使用 Java8 Stream 从对象中获取多个字段值来从 List<Object> 创建 HashSet?

java - 从 Java 读取来自 MQ 的所有消息

流并行中的 Java 8 流

android - BufferedReader 的错误使用

c++ - C++ 中的 Bittorrent 客户端,连接到非阻塞套接字上的对等点总是超时

java - 为什么 Java 8's functional-style constructs called "流”?

java - 使用动态correlationId从ibm mq异步接收值

java - where 子句中的查询语法错误