Java 套接字的缓冲读取器从未就绪

Java 套接字的缓冲读取器从未就绪,java,sockets,bufferedreader,java-threads,Java,Sockets,Bufferedreader,Java Threads,为了完全透明,这是一项任务 还有很多事情要做,但目前我只是想做以下几点: 节点A从文本文件读入 节点A使用套接字将文本文件(减去第一行)发送给节点B 节点B从所述套接字读入,并将其打印到控制台 然而,现在,要么信息没有被发送,要么节点B没有正确读取 在我的主类中,我设置了如下节点: NodeA nodeA = new NodeA(); NodeB nodeB = new NodeB(); new Thread(nodeA).start(); new Thread(nodeB).start();

为了完全透明,这是一项任务

还有很多事情要做,但目前我只是想做以下几点:

  • 节点A从文本文件读入
  • 节点A使用套接字将文本文件(减去第一行)发送给节点B
  • 节点B从所述套接字读入,并将其打印到控制台
  • 然而,现在,要么信息没有被发送,要么节点B没有正确读取

    在我的主类中,我设置了如下节点:

    NodeA nodeA = new NodeA();
    NodeB nodeB = new NodeB();
    
    new Thread(nodeA).start();
    new Thread(nodeB).start();
    
    在节点A中,我执行以下操作:

    //Open a socket for talking with NodeB
    Socket mySocket = new Socket(InetAddress.getLocalHost(), portNum);
    
    //Set up the socket's output
    PrintWriter out = new PrintWriter(mySocket.getOutputStream(), true);
    
    //Loop through the lines of the confA file, writing them to the socket
    String line = bufferedReader.readLine();
    while (line != null)
    {
        //Write the line to the socket, get the next line
        out.println(line); //updated to println, this flushes and fixes another problem
        out.flush();
        line = bufferedReader.readLine();
    }
    
    //Close the socket
    mySocket.close();
    
    请注意,节点A的循环工作正常。当我使用打印语句进行测试时,它不会永远循环,并且会遍历预期的文本行

    然后,在节点B端:更新以显示当前节点B代码

    //Open the socket 
    ServerSocket mySocket = new ServerSocket(portNum);
    Socket connectionSocket = mySocket.accept();
    
    //Set up a reader on the socket to get what's coming from it
    BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
    
    String line = in.readLine(); //hang occurs here
    
    while(line != null) {
        System.out.println(line);
        line = in.readLine();;
    }
    
    然而,in.ready()永远都不是真的。我尝试过使用while循环等待这种情况发生,但从未发生过

    我真的不知道为什么。我不知道我是否正确设置了套接字,是否正确设置了服务器,是否正确侦听,等等

    我只是觉得把B变成一个监听a的服务器是最有意义的。我希望这是对的。它看起来和我在网上看到的其他一些例子很相似

    谢谢你的帮助。我对套接字、端口、侦听和其他方面非常不熟悉,所以如果我一开始不理解您的建议,请原谅我。我会尽力去理解它


    我没有添加整个代码,希望能让它更具可读性,更清楚问题所在,但如果您需要更多信息,请随时询问,我会尽力提供。

    服务器必须首先从服务器套接字获取套接字,然后将套接字发送到客户端

    connectionSocket = mySocket.accept();
    
    服务器线程将处于休眠状态,直到客户端使其接受connectionSocket

    然后可以从connectionSocket中读取<代码>就绪不需要

    由于这是一项任务,剩下的就交给你了


    顺便说一句,一台典型的服务器可以做到:

    for (;;) {
        Socket socket = serverSocket.accept();
        ... pass the socket to a thread from a pool of threads
    }
    

    服务器必须首先从服务器套接字获取套接字到客户端

    connectionSocket = mySocket.accept();
    
    服务器线程将处于休眠状态,直到客户端使其接受connectionSocket

    然后可以从connectionSocket中读取<代码>就绪不需要

    由于这是一项任务,剩下的就交给你了


    顺便说一句,一台典型的服务器可以做到:

    for (;;) {
        Socket socket = serverSocket.accept();
        ... pass the socket to a thread from a pool of threads
    }
    

    我认为问题在于ready仅仅意味着如果你调用read,它不会阻塞。如果在grepcode上查找函数,可以看到执行的代码:

    一个就绪线程只是意味着它不会阻塞,当你想确保你的线程不会被阻塞时,这是很有用的,但并不能真正告诉你是否有缓冲区

    您要做的是执行readline,作为阻塞调用,直到数据被消耗为止。如果你不想让它阻塞你当前的线程,那么就为这个读到的线程派生一个新的消费者线程,它可以阻塞


    此外,请确保您正在使用关闭的套接字或刷新来结束发送通信,以指示消费流何时完成。每个打开/关闭会话只需要接受一次套接字。

    我认为问题在于就绪只意味着如果调用read,它不会阻塞。如果在grepcode上查找函数,可以看到执行的代码:

    一个就绪线程只是意味着它不会阻塞,当你想确保你的线程不会被阻塞时,这是很有用的,但并不能真正告诉你是否有缓冲区

    您要做的是执行readline,作为阻塞调用,直到数据被消耗为止。如果你不想让它阻塞你当前的线程,那么就为这个读到的线程派生一个新的消费者线程,它可以阻塞


    此外,请确保您正在使用关闭的套接字或刷新来结束发送通信,以指示消费流何时完成。每个打开/关闭会话只需接受一次套接字。

    感谢您的回复,但有几件事仍然让人感到困惑。一旦服务器完成等待并且客户端连接,我就不需要再执行另一个.accept(),对吗?我试图更改我的代码,以便只使用首字母。accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。您应该只有一个
    ServerSocket。accept
    生成一个可从中读取的套接字。谢谢。我已经更新了代码,删除了额外的.accepts()和.ready(),现在显示了挂起发生的位置。好的,您已经看到了。在客户端执行
    println
    而不是
    print
    。这会将缓冲区刷新到输出。一个
    新的PrintWriter(…,true)
    会在println上自动刷新。在我身边晚安,谢谢!它现在似乎工作得很好。我想知道为什么在我尝试时,结果会变成一行。flush()。现在我可以把它删除了。谢谢你的回复,但是有一些事情仍然让人很困惑。一旦服务器完成等待并且客户端连接,我就不需要再执行另一个.accept(),对吗?我试图更改我的代码,以便只使用首字母。accept,但我似乎仍然无法从套接字读取,它只是永远挂在readLine()上。您应该只有一个
    ServerSocket。accept
    生成一个可从中读取的套接字。谢谢。我已经更新了代码,删除了额外的.accepts()和.ready(),现在显示了挂起发生的位置。好的,您已经看到了。在客户端执行
    println
    而不是
    print
    。这会将缓冲区刷新到输出。一个
    新的PrintWriter(…,true)
    会在println上自动刷新。在我身边晚安,谢谢!它现在似乎工作得很好。我习惯了