Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ServerSockets和Sockets时,BufferedReader将挂起,并且连接似乎不';不能正确地形成_Java_Sockets_Bufferedreader_Serversocket - Fatal编程技术网

Java 使用ServerSockets和Sockets时,BufferedReader将挂起,并且连接似乎不';不能正确地形成

Java 使用ServerSockets和Sockets时,BufferedReader将挂起,并且连接似乎不';不能正确地形成,java,sockets,bufferedreader,serversocket,Java,Sockets,Bufferedreader,Serversocket,编辑:我已通过在服务器代码中添加一行更正了代码中的以下错误 我正在尝试编写一些套接字代码,允许我为一个游戏将数据从一台计算机发送到另一台计算机(为了简单起见,我们可以将其视为tic-tac-toe,不需要发送太多数据,只需发送几个数字)。为了实现这一点,我编写了两个类,Server和Client。目前,我正在使用端口1234通过本地主机进行测试,并且我只使用了该程序的一个实例(尽管在尝试使用两个实例时也会出现同样的问题) 首先是代码,然后我可以更深入地了解这个问题,以及我做了哪些测试来试图找出问

编辑:我已通过在服务器代码中添加一行更正了代码中的以下错误

我正在尝试编写一些套接字代码,允许我为一个游戏将数据从一台计算机发送到另一台计算机(为了简单起见,我们可以将其视为tic-tac-toe,不需要发送太多数据,只需发送几个数字)。为了实现这一点,我编写了两个类,
Server
Client
。目前,我正在使用端口1234通过本地主机进行测试,并且我只使用了该程序的一个实例(尽管在尝试使用两个实例时也会出现同样的问题)

首先是代码,然后我可以更深入地了解这个问题,以及我做了哪些测试来试图找出问题所在:

public class Server
{
    private ServerSocket server;
    private Socket socket;

    private Client socketHandler;

    private static final int DEFAULT_PORT = 1234;

    public Server() { this(DEFAULT_PORT); }
    public Server(int port)
    {
        Thread thread = new Thread()
        {
            public void run()
            {
                try
                {
                    System.out.println("Attempting to Establish Connection");
                    server = new ServerSocket(port);
                    socket = server.accept();
                    socketHandler = new Client(port, socket); //THIS LINE ADDED
                    System.out.println("Server Online!");
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        };

        thread.setDaemon(true);
        thread.start();
    }

    //ADJUSTED
    Client getSocketHandler()
    {
        return socketHandler;
    }

    public void kill()
    {
        try
        {
            if (socket != null) socket.close();
            if (server != null) server.close();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            socket = null;
            server = null;
        }
    }
}

public class Client
{
    public static final int DEFAULT_PORT = 1234;
    public static final String DEFAULT_HOST = "localhost";
    private static final String THUMP_THUMP = "thump thump";
    private static final int PULSE = 1000;

    private int port;
    private String ip;

    private Socket socket;
    private BufferedReader input = null;
    private PrintWriter output = null;

    boolean closed = true;

    String data = "";

    public Client() { this(DEFAULT_PORT, DEFAULT_HOST, null); }
    public Client(int port) { this(port, DEFAULT_HOST, null); }
    public Client(int port, String ip) { this(port, ip, null); }
    public Client(int port, Socket server) { this(port, DEFAULT_HOST, server); }
    public Client(String ip) { this(DEFAULT_PORT, ip, null); }
    public Client(String ip, Socket server) { this(DEFAULT_PORT, ip, server); }
    public Client(Socket server) { this(DEFAULT_PORT, DEFAULT_HOST, server); }
    public Client(int port, String ip, Socket server)
    {
        socket = server;
        this.ip = ip;
        this.port = port;

        Thread thread = new Thread()
        {
            public void run()
            {                
                try
                {
                    initialise(server);
                    String line;
                    startHeartbeat();
                    while (isClosed()) {} //first it is closed, lets wait for it to open before we start waiting for it to close!
                    System.out.println("We are about to listen!");
                    while (!isClosed())
                    {
                        System.out.println("pre-read"); //this line was used to determine that the code was hanging on the next line
                        line = input.readLine(); //offending line
                        System.out.println("post-read"); //this line was used to determine when the block was lifted
                        if (line != null)// || line != THUMP_THUMP)
                        {
                            System.out.println(line);
                            data += line + "\n";
                        }
                    }
                    System.out.println(data);
                    kill();
                    System.out.println("Connection Closed!");
                }
                catch (SocketException e)
                {
                    e.printStackTrace();
                    System.out.println("Server closed!");
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        };

        thread.setDaemon(true);
        thread.start();
    }

    private void initialise(Socket server)
    {
        try
        {
            if (server == null) socket = new Socket(ip, port);
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
        }
        catch (IOException e) { e.printStackTrace(); }
    }

    public boolean post(String text)
    {
        synchronized(this)
        {
            output.println(text);
            output.flush();
            return !output.checkError();
        }
    }

    public void kill()
    {
        try
        {
            if (input != null) input.close();
            if (socket != null) socket.close();
        }
        catch(IOException e) { e.printStackTrace(); }
        finally
        {
            input = null;
            socket = null;
        }
    }

    public void killOutputStream()
    {
        try
        {
            if (output != null) output.close();
        }
        catch (Exception e) { e.printStackTrace(); }
        finally
        {
            output = null;
        }
    }

    //////////////////////////////////
    ///////// Socket Control /////////
    //////////////////////////////////

    synchronized boolean isClosed()
    {
        return closed;
    }

    synchronized void setClosed(boolean b)
    {
        closed = b;
    }

    //We need to make sure that the socket is still online, to ensure the reading stops when the connection closes.
    void startHeartbeat()
    {
        Thread heartbeat = new Thread()
        {
            public void run()
            {
                while (output != null)
                {
                    setClosed(post(THUMP_THUMP) ? false : true); //post returns true on success
                    synchronized(this)
                    {
                        try
                        {
                            this.wait(PULSE);
                        }
                        catch (InterruptedException e) {}
                    }
                }
                setClosed(true);
            }
        };
        heartbeat.setDaemon(true);
        heartbeat.start();
    }
}
问题

当客户端启动时(在创建服务器之后),它无法读取通过(甚至心跳)发送的任何数据,事实上,代码不会经过读取线程中的
line=input.readLine()
(从现在起称为违规行),除非服务器断开连接(见下文)

以下是定期测试的顺序:

调用
Server()
,得到的
Server
存储在
serverConnection
变量中
Client(serverConnection!=null?serverConnection.getSocket():null)
被调用,新的
Client
存储在
clientConnection

因为我们可以使用heartbeat测试它是否工作,所以不需要发送其他数据,通过调用
serverConnection.kill()
,然后在等待一段时间后调用
clientConnection.killOutputStream()
来终止服务器

这就是结果:

Attempting to Establish Connection Server Online! 
We are about to listen!

Connection Closed!
其中,空行表示在连接过程中接收到的非空数据,即不存在任何数据

我期望:

Attempting to Establish Connection
Server Online!
We are about to listen!
thump thump
thump thump
thump thump (and so on, every second)
Connection closed!
我花时间执行不同的测试,用相同的测试格式注释掉或稍微更改代码(特例除外,第6号),并进行了以下观察:

观察结果

  • 只有当套接字被关闭并且输出流被关闭时,程序才会越过有问题的行
  • readline()
    方法开始处理时(心跳停止前不久),它在流中检测不到任何内容,甚至
    THUMP\u-THUMP
  • 当套接字关闭,但输出流未关闭时,
    readline()
    方法开始处理,结果检测不到任何内容,heartbeat将其切断。无
    SocketException
    ,即使它是预期的
  • 如果套接字未关闭,并且只有输出流关闭,则会触发
    SocketException
    ,提示套接字已关闭
  • 我在命令提示符中使用了
    netstat-an
    ,当服务器启动时,端口1234正在侦听。当客户端连接时,它仍在侦听,这意味着没有连接
  • 我设置了一些python代码通过端口1234连接到自身, 但是,我在python代码中犯了一个错误,因此服务器也犯了一个错误 没有关闭,但仍然打开。所以我决定连接java 客户端连接到服务器并查看发生了什么。我是通过跑步来做到这一点的
    Client(null)
    这是非主机的客户端代码。信息技术 导致端口读取建立,并且python服务器 回响“砰砰”的一声,java代码就成功了 读它。没有绞刑,它工作得很好
  • 这使我相信问题在于服务器代码,因为python服务器能够成功地与Java客户机通信,但Java客户机无法与Java服务器通信

    在执行此测试之前,我一直专注于客户机代码,认为它有错。我在这里发现的所有具有类似症状的问题(请参阅,以及其他问题)在我看来都是空白的,因为我已经将它们的答案写了出来(大多数原因是由于输出流未刷新,或\n未写入,我没有失败,或解决方案没有解决我的问题,因此在本例中已被删除,以支持heartbeat)。我最初基于本文编写的代码

    经过4天的努力解决这个问题后,我不知所措,不知该怎么办…我在这里遗漏了什么?为什么服务器代码没有按照我的预期工作?如果有人需要对我的代码进行更多的澄清,请询问


    作为一个补充说明,测试代码是通过一个用javafx(不是fxml)编写的简单的极简GUI运行的,无论这是否是一个问题,我肯定,我认为不会,因为它与Python服务器一起工作。这段代码是用Java 8编译的。我有点不明白为什么您认为它会比input.readLine更进一步()考虑到服务器端没有处理输入/输出

    客户端/服务器连接就像一场网球比赛,因为一方发球另一方必须先接到球,然后再发回(可能有不同的信息)。服务器端必须处理从start heartbeat方法收到的输入,然后向您发回响应。input.readLine()函数将阻塞线程,直到它从另一端接收数据为止,因此是的,代码将在那里停止,并等待服务器将“网球”发回。在服务器类中,您应该添加一个处理心跳输入的输入和输出流,并将一串数据发回客户端

    服务器:

    OutputStream os = socket.getOutputStream();
    InputStream is = socket.getInputStream();
    String response = "thump thump";
    
    while(true){
        is.read();
        os.write(response.getBytes());
        os.flush();
    }
    

    在本例中,客户端应保持不变,只需将上述代码添加到服务器。

    很抱歉,您的代码看起来很混乱,首先,您没有将任何数据从服务器发送到客户端,服务器也没有发送到客户端