BufferReader not receiving data from socket apparently. Simple chat service

huangapple 未分类评论41阅读模式
英文:

BufferReader not receiving data from socket apparently. Simple chat service

问题

请您友好地查看我的代码,并告诉我可能出现的问题是什么?
我正在学习Java网络编程和网络通信,纯粹是为了好玩,我尝试遵循这个链接https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html 中的内容,但我并没有创建协议,而是尝试在服务器和客户端之间创建简单的消息交换。

标准输出没有显示任何内容,当我进行调试时,BufferReader缓冲区为空,似乎没有接收到数据。我还没有使用Wireshark进行检查,但我怀疑问题可能更加琐碎,是由于我经验不足造成的结果。

以下是客户端代码(它首先向服务器发送简单的消息“Hello There”):

try (BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter toServer = new PrintWriter(socket.getOutputStream());
    BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {

    toServer.println("Hello there!");

    while (!goodbye) {
        if (fromServer.ready()) //如果流为空,这会防止冻结
            msgFromServer = fromServer.readLine();
        if (msgFromServer != null) {
            System.out.println("Server: " + msgFromServer);
            if (msgFromServer.equals("Bye"))
                goodbye = true;
        }

        msgToServer = consoleInput.readLine();
        if (msgToServer != null) {
            toServer.println(msgToServer);
            if (msgToServer.equals("Bye"))
                goodbye = true;
        }
    }
    socket.close();
} catch (IOException e) {
    e.printStackTrace();
}

现在是服务器端

try (Socket clientSocket = socket.accept();
    BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream());
    BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {
    while (!goodbye) {
        if (fromClient.ready())
            msgFromClient = fromClient.readLine();
        if (msgFromClient != null) {
            System.out.println("Client: " + msgFromClient);
            if (msgFromClient.equals("Bye"))
                goodbye = true;
        }

        msgToClient = consoleInput.readLine();
        if (msgToClient != null) {
            toClient.println(msgToClient);
            if (msgToClient.equals("Bye"))
                goodbye = true;
        }
    }
    socket.close();
} catch (IOException ex) {
    System.out.println(ex);
}

我已经有点困惑,因为有太多的循环,我想知道它们是否可能出现问题,我的策略是否总体上是错误的?也许我应该设置一些标志,比如“等待服务器回复”。我真的很困惑。

编辑:在每个类中注释掉 if (BufferedReader.ready()) 方法之后,它就工作了。不过我仍然不确定为什么会这样,所以我不会立刻关闭它,但在找到答案后,我会在另一个回答中进行解释。
到目前为止,我的“修复”代码看起来像这样:

try (Socket clientSocket = socket.accept();
    BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
    BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
) {
    while (!goodbye) {
        // if (fromClient.ready())
        msgFromClient = fromClient.readLine();
        if (msgFromClient != null) {
            System.out.println("Client: " + msgFromClient);
            if (msgFromClient.equals("Bye"))
                goodbye = true;
        }

        msgToClient = consoleInput.readLine();
        if (msgToClient != null) {
            toClient.write(msgToClient);
            toClient.newLine();
            toClient.flush();
            if (msgToClient.equals("Bye"))
                goodbye = true;
        }
    }
    socket.close();
} catch (IOException ex) {
    System.out.println(ex);
}

我忘记了,但我还添加了 Socket.TcpSetNoDelay(true) 到客户端套接字中。

英文:

Could You kindly take a glance at my code and tell me what could be the problem here?
I am learning java network programming and networking in general for fun and i try to follow this https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html but instead of creating protocol i try to just create simple exchange of messages between server and client.

Nothing shows up in standard output and when i am debugging it BufferReader buffer is empty and seems to not receive data. I have yet to check it with Wireshark but i suspect cause is much more trivial and a result of my inexperience.

Here is the client code (It messages server first with a simple "Hello There")

 try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter toServer = new PrintWriter(socket.getOutputStream());
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
    ){

        toServer.println("Hello there!");

        while(!goodbye){
            if(fromServer.ready())                        //if stream is empty this prevents a freeze
                msgFromServer = fromServer.readLine();
            if(msgFromServer != null) {
                System.out.println("Server: " + msgFromServer);
                if(msgFromServer.equals("Bye"))
                    goodbye = true;
            }

            msgToServer = consoleInput.readLine();
            if(msgToServer != null) {
                toServer.println(msgToServer);
                if(msgToServer.equals("Bye"))
                    goodbye = true;
            }

        }
        socket.close();

    } catch (IOException e) {
        e.printStackTrace();
    }

And now server side:

      try(Socket clientSocket = socket.accept();
            BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter toClient = new PrintWriter(clientSocket.getOutputStream());
            BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
        ){

            while(!goodbye){
                if(fromClient.ready())
                    msgFromClient = fromClient.readLine();
                if(msgFromClient != null) {
                    System.out.println("Client: " + msgFromClient);
                    if(msgFromClient.equals("Bye"))
                        goodbye = true;
                }

                msgToClient = consoleInput.readLine();
                if(msgToClient != null) {
                    toClient.println(msgToClient);
                    if(msgToClient.equals("Bye"))
                        goodbye = true;
                }

            }

            socket.close();

        } catch(IOException ex){
            System.out.println(ex);
        }

I am a bit confused already by all the loops and wonder if it is possible they are out of sync somehow and my strategy is generally wrong ? perhaps should i set some flags as "waiting_for_server_reply" I am really confused

Edit: After commenting out if(BufferedReader.ready())
methods in each class it worked. I am still unsure why though so i won't close it just yet but after i find answer i will explain in separate answer
So far my 'fixed' code looks like:

 try(Socket clientSocket = socket.accept();
            BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
        ){

            while(!goodbye){
                //if(fromClient.ready())
                    msgFromClient = fromClient.readLine();
                if(msgFromClient != null) {
                    System.out.println("Client: " + msgFromClient);
                    if(msgFromClient.equals("Bye"))
                        goodbye = true;
                }

                msgToClient = consoleInput.readLine();
                if(msgToClient != null) {
                   toClient.write(msgToClient);
                   toClient.newLine();
                   toClient.flush();                        
                    if(msgToClient.equals("Bye"))
                        goodbye = true;
                }

            }

            socket.close();

        } catch(IOException ex){
            System.out.println(ex);
        }

I forgot but i also added Socket.TcpSetNoDelay(true) to client Socket

答案1

得分: 0

我认为你应该尝试使用熟悉的类来进行读写操作。例如,如果你正在使用 BufferedReader 进行读取,那么写入时应该使用 BufferedWriter

英文:

I think you should try to use familiar classes for reading and writing. For example if you are using BufferedReader for reading then you should use BufferedWriter for writing.

答案2

得分: 0

在每个类中注释掉 if(BufferedReader.ready()) 方法后,它就正常工作了。看起来我对这个方法的作用有误解。我添加了 .ready() 方法,因为服务器在从客户端的流中读取数据后没有使用 flush() 方法,导致在调试过程中出现了服务器在 .readLine() 处冻结的情况,并且指示可能会有问题。

正如 @VGR 指出的那样,ready() 方法只是用来判断是否存在等待流数据到达的延迟。第一条消息必须有延迟,所以直到下一个缓冲区读取时才显示,当缓冲区中已经有内容时。

我还在客户端的 Socket 中添加了 Socket.TcpSetNoDelay(true)

现在代码看起来是这样的:

服务器:

try(Socket clientSocket = socket.accept();
        BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
    ){

    while(!goodbye){
        //if(fromClient.ready())
            msgFromClient = fromClient.readLine();
        if(msgFromClient != null) {
            System.out.println("Client: " + msgFromClient);
            if(msgFromClient.equals("Bye"))
                goodbye = true;
        }

        msgToClient = consoleInput.readLine();
        if(msgToClient != null) {
           toClient.write(msgToClient);
           toClient.newLine();
           toClient.flush();                        
            if(msgToClient.equals("Bye"))
                goodbye = true;
        }

    }

    socket.close();

} catch(IOException ex){
    System.out.println(ex);
}

客户端:

Clientv2(){
    socket = new Socket();
    try {
        socket.setTcpNoDelay(true); //this is new too
    } catch (SocketException e) {
        e.printStackTrace();
    }
}

public void connect() {
    try {
        socket.connect(new InetSocketAddress(serverHostname, serverPort));
    }
    catch (IOException ex){
        System.out.println(ex);
    }

    try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter toServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
    ){

    toServer.write("Hello there!");
    toServer.newLine();
    toServer.flush();

    while(!goodbye){
        //if(fromServer.ready())                        //culprit
            msgFromServer = fromServer.readLine();
        if(msgFromServer != null) {
            System.out.println("Server: " + msgFromServer);
            if(msgFromServer.equals("Bye"))
                goodbye = true;
        }

        msgToServer = consoleInput.readLine();
        if(msgToServer != null) {
            toServer.write(msgToServer);
            toServer.newLine();
            toServer.flush();
            if(msgToServer.equals("Bye"))
                goodbye = true;
        }

    }
    socket.close();
}
英文:

After commenting out if(BufferedReader.ready()) methods in each class it worked.
It looks like i had wrong idea what this method is doing.
I added the .ready() method because server froze on .readLine() because i didn't use flush() method after writing to the stream from the client and during debugging it indicated that there may be a problem here.

As @VGR pointed out
All the ready() method does is telling whether there was a delay waiting for stream data to arrive or not. First message had to have a delay so it didn't show until the next buffer read when it was already something in the buffer.

I also added Socket.TcpSetNoDelay(true) to client Socket

Code now looks like this
Server:

try(Socket clientSocket = socket.accept();
        BufferedReader fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        BufferedWriter toClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
    ){

        while(!goodbye){
            //if(fromClient.ready())
                msgFromClient = fromClient.readLine();
            if(msgFromClient != null) {
                System.out.println("Client: " + msgFromClient);
                if(msgFromClient.equals("Bye"))
                    goodbye = true;
            }

            msgToClient = consoleInput.readLine();
            if(msgToClient != null) {
               toClient.write(msgToClient);
               toClient.newLine();
               toClient.flush();                        
                if(msgToClient.equals("Bye"))
                    goodbye = true;
            }

        }

        socket.close();

    } catch(IOException ex){
        System.out.println(ex);
    }

Client

Clientv2(){
    socket = new Socket();
    try {
        socket.setTcpNoDelay(true); //this is new too
    } catch (SocketException e) {
        e.printStackTrace();
    }
}

public void connect() {
    try {
        socket.connect(new InetSocketAddress(serverHostname, serverPort));
    }
    catch (IOException ex){
        System.out.println(ex);
    }

    try(BufferedReader fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter toServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
    ){

        toServer.write("Hello there!");
        toServer.newLine();
        toServer.flush();

        while(!goodbye){
            //if(fromServer.ready())                        //culprit
                msgFromServer = fromServer.readLine();
            if(msgFromServer != null) {
                System.out.println("Server: " + msgFromServer);
                if(msgFromServer.equals("Bye"))
                    goodbye = true;
            }

            msgToServer = consoleInput.readLine();
            if(msgToServer != null) {
                toServer.write(msgToServer);
                toServer.newLine();
                toServer.flush();
                if(msgToServer.equals("Bye"))
                    goodbye = true;
            }

        }
        socket.close();

huangapple
  • 本文由 发表于 2020年7月27日 03:23:57
  • 转载请务必保留本文链接:https://java.coder-hub.com/63104677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定