BufferedReader会导致连接重置吗?

3

我正在尝试使用Java从客户端向服务器发送一些数据,这里是我的PlayerThread,当一个新的客户端连接时,在服务器上运行

PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
        //Create a link to send data to the server
        BufferedReader in = new BufferedReader(
                new InputStreamReader(
                socket.getInputStream()));
        while(true)
        {
            out.println(pongData);
            String temp = in.readLine();
            if(temp == "up")
            {
                System.out.println("Up you say");
            }
        }
//There is a little more but no point to give it all

当客户端断开连接时,该行代码 String temp = in.readLine(); 会给我返回以下错误:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Pong.PongPlayerThread.run(PongPlayerThread.java:36)

这里是客户端代码。
try
    {
        socket = new Socket(host, port);
        serverOut = new PrintWriter(socket.getOutputStream(), true);
        serverInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }
    catch (UnknownHostException e)
    {
        System.err.println("Couold not connect to host:" + host);
        System.exit(1);
    }
    catch (IOException e)
    {
        System.err.println("Could not get Input/Output from server");
        System.exit(1);
    }

    System.out.println("Connected to Server");

    while ((pos = serverInput.readLine()) != null) 
    {
        String[] posValues = pos.split(":");
        model.getBall().setX(Double.parseDouble(posValues[0]));
        model.getBall().setY(Double.parseDouble(posValues[1]));

        if(PongController.moveUp == true)
        {
            serverOut.println("up");
            PongController.moveUp = false;
        }

        //If the client presses up or down arrow, a message will be sent to the server
        //the server will then update the movement and the clients will be able to see it

    }

这段代码是有效的,但似乎完全没有发送消息 :( 如果有人能帮我解决这个问题就太好了。
画布
我刚刚编辑了一些代码,并发现在PlayerThread中,这几行:
if(temp.equals("up"))
            {
                System.out.println("Up you say");
            }

问题是,客户端流在开始时设置为无,这可能是问题吗?发送空值?

这是更新版本。

    while ((pos = serverInput.readLine()) != null) 
    {
        String[] posValues = pos.split(":");
        model.getBall().setX(Double.parseDouble(posValues[0]));
        model.getBall().setY(Double.parseDouble(posValues[1]));
        serverOut.println("nothing");

        if(PongController.moveUp == true)
        {
            System.out.println("Up");
            serverOut.println("up");
            PongController.moveUp = false;
        }
        else
        {
            serverOut.println("nothing");
        }

    }

但我仍然得到相同的错误

检查in.readLine是否等于任何内容,我得到了这个代码

try
    {
        PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
         BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                    socket.getInputStream()));

         System.out.println("Checking readLine value");

         if(in.readLine() == null)
         {
             System.out.println("A ok");
         }
         else
         {
             System.out.println(":" + in.readLine());
         }

        while(true)
        {
             String temp = in.readLine();
             if(temp == "up")
             {
                    System.out.println("Up you say");
             }
            out.println(pongData);
        }
    }
    catch (IOException e) 
    {
        e.printStackTrace();
    }

这是结果

Pong
400.0:301.0:60.0:300.0:740.0:300.0
Server started
Server was setup and will try to create a socket
Data sent
Checking readLine value
Connection reset, and then followed by lots of red lines

还有什么我可以做吗?

我刚刚尝试使用以下方法来检查我的 BufferedReader:

BufferedReader in = new BufferedReader(
                    new InputStreamReader(
                    socket.getInputStream()));

        System.out.println(in.toString());
        System.out.println(in.readLine());

我获得了java.io.BufferedReader@6262937c来读取in.toString的内容,但是对于readLine方法,我又一次收到了连接重置的错误信息...

快速更新,

在我的客户端代码中,如果我加入以下内容:

 while ((pos = serverInput.readLine()) != null) 
    {
        String[] posValues = pos.split(":");
        model.getBall().setX(Double.parseDouble(posValues[0]));
        model.getBall().setY(Double.parseDouble(posValues[1]));
        serverOut.println("nothing"); //<---

客户端将会连接,获取乒乓球的位置,但随后就无法再从服务器接收数据,只能按照自己的意愿移动球(更新方法尚未被禁用)。服务器输出为

serverOut = new PrintWriter(socket.getOutputStream(), true);

2
除此之外,您正在错误地比较字符串...请参见http://tinyurl.com/so-java-string-equality - Jon Skeet
1
你所看到的连接重置是有文档记录的行为,这也是为什么大多数通信协议今天都包括它们正在发送的消息的长度,例如HTTP的“Content-Length”头值。 - Brian
好的Jon,我已经改了,但是仍然得到相同的错误。 - Canvas
Brian,我按照教程操作,教程上一切正常,但是在我的项目中就无法运行,肯定还有其他原因导致这种情况。 - Canvas
在你对readLine()返回的值进行任何操作之前,你还需要检查它是否为null。如果返回null,那么对等方已经关闭了连接,你必须做同样的事情,并且当然要退出读取循环。 - user207421
显示剩余20条评论
2个回答

8

好的,我注意到您最近一直在询问有关网络的问题,我想也许您需要一些基础帮助。这是一个非常简单的服务器:

package com;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer implements Runnable
{    
    public SimpleServer()
    {
        started = false;
        serverSocket = null;
    }

    public void start()
    {
        if(!started)
        {
            started = true;

            try
            {
                serverSocket = new ServerSocket(PORT);
                running = true;

                serverThread = new Thread(this);
                serverThread.start();

                System.out.println("Server started!\n");
            }catch(Exception e)
            {
                e.printStackTrace();
                System.exit(0);
            }
        }
    }

    public void stop()
    {
        running = false;
        started = false;

        if(serverThread != null)
            serverThread.interrupt();
        serverThread = null;
    }

    public void run()
    {
        try
        {
            while(running)
            {
                try
                {
                    Socket client = serverSocket.accept();
                    System.out.println("Client Accepted!");

                    ClientHandler handler = new ClientHandler(client);

                    handler.sendMessage("Hello, SimpleClient!");
                    System.out.println("Sendeing client a message...");
                }catch(Exception e){e.printStackTrace();}
            }
        }catch(Exception e){e.printStackTrace();}
    }

    private boolean started;
    private boolean running;
    private ServerSocket serverSocket;
    private Thread serverThread;

    private static final int PORT = 8081;

    public static void main(String args[])
    {
        SimpleServer server = new SimpleServer();
        server.start();
    }

    public class ClientHandler implements Runnable
    {
        public ClientHandler(Socket socket)
        {
            this.socket = socket;

            try
            {
                writer = new PrintWriter(socket.getOutputStream());
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                running = true;

                runningThread = new Thread(this);
                runningThread.start();
            }catch(Exception e){e.printStackTrace(); disconnect();}
        }

        public void disconnect()
        {
            running = false;
            if(runningThread != null)
                runningThread.interrupt();
            runningThread = null;

            try
            {
                reader.close();
            }catch(Exception e){}
            reader = null;

            try
            {
                writer.close();
            }catch(Exception e){}
            writer = null;
            try
            {
                socket.close();
            }catch(Exception e){}
            socket = null;
        }

        public void sendMessage(String message)
        {
            if(running)
            {
                writer.println(message);
                writer.flush();
            }
        }

        public void run()
        {
            try
            {
                String message = "";
                while((message = reader.readLine()) != null && running)
                {
                    System.out.println("Message Recieved: " + message);
                }
            }catch(Exception e){e.printStackTrace(); disconnect();}
        }

        private Socket socket;
        private PrintWriter writer;
        private BufferedReader reader;

        private Thread runningThread;
        private boolean running;
    }
}

现在这里是客户端:

package com;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class SimpleClient implements Runnable
{
    public SimpleClient()
    {
        try
        {
            socket = new Socket("127.0.0.1", PORT);
            writer = new PrintWriter(socket.getOutputStream());
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            running = true;

            runningThread = new Thread(this);
            runningThread.start();
        }catch(Exception e){e.printStackTrace(); disconnect();}
    }

    public void disconnect()
    {
        running = false;
        if(runningThread != null)
            runningThread.interrupt();
        runningThread = null;

        try
        {
            reader.close();
        }catch(Exception e){}
        reader = null;

        try
        {
            writer.close();
        }catch(Exception e){}
        writer = null;
        try
        {
            socket.close();
        }catch(Exception e){}
        socket = null;
    }

    public void sendMessage(String message)
    {
        if(running)
        {
            writer.println(message);
            writer.flush();
        }
    }

    public void run()
    {
        try
        {
            String message = "";
            while((message = reader.readLine()) != null && running)
            {
                System.out.println("Message Recieved: " + message);

                System.out.println("Sending a response!");
                sendMessage("Hello, SimpleServer!");
            }
        }catch(Exception e){e.printStackTrace(); disconnect();}
    }

    private Socket socket;
    private PrintWriter writer;
    private BufferedReader reader;

    private Thread runningThread;
    private boolean running;

    private static final int PORT = 8081;

    public static void main(String args[])
    {
        new SimpleClient();
    }
}

为了成功地在Java中创建服务器,您需要实现大量的面向对象编程。如果服务器不仅需要监听客户端还需与客户端发送和接收消息,则该过程会变得非常复杂。这就是我通常使用ClientHandler类的原因。该类处理所有通信,并且非常容易实现。客户端和服务器不应该在同一个文件中,因为它们是分别运行的。
如果您不确定服务器和客户端应该如何工作,下面的链接可能会对您有所帮助: 希望这可以帮到您!
John

我很快就会看一下,并且肯定会尝试一下,我对网络编程还很陌生,似乎只是编写一个程序就变得非常复杂:D,但感谢您的帖子,我很快就会尝试。 - Canvas
好的,如果你有更多问题,请让我知道;如果你需要更多示例代码,请告诉我。谢谢! - John
John,你能否看一下我的另一个问题?我已经得到了一些帮助,但现在遇到了另一个错误,我不确定客户端是否需要自己的线程来接收和发送数据。链接在这里:http://stackoverflow.com/questions/14914027/java-client-to-server-unknown-source - Canvas
这里有一些我不理解的东西 - 这段代码与他的方法有什么很大的区别,除了代码组织方面,他做错了什么? - kutschkem
1
@kutschkem 当我查看他的代码时,我没有立即发现任何问题。我看到它的结构很差。他正在使用阻塞服务器而不在单独的线程上运行它,这是一个结构问题。他也没有在每个客户端连接上运行自己的线程,这也是一个结构问题。代码已经存在,但结构不正确。网络编程非常复杂,需要良好的结构才能正常运行。 - John

1

刚刚把我的代码改成了这样: if(PongController.moveUp == true) { serverOut.println("up"); serverOut.flush(); System.out.println("is did send"); PongController.moveUp = false; }但还是没有任何反应 :( - Canvas
1
你考虑过使用 WireShark 监视 TCP 流吗? - Charlie
从来没有用过,它容易使用吗? - Canvas
您可以右键单击下方窗格中的字段以构建筛选器,这将至少为工具栏中的筛选字段的语法提供一个想法。 - Charlie
@Charlie Wireshark甚至看不到与127.0.0.1通信的数据包,因为它们没有通过网络线路传输。 - user207421
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接