套接字从TimerTask.run()内部关闭

时间:2016-02-29 13:20:31

标签: java

我有一个服务器套接字。在TimerTask的帮助下,它每1秒查询服务器并通过输出/输入流读取响应。但是,我收到错误套接字已关闭

try (
        // create TCP socket for the given hostName, remote port PortNumber
        Socket echoSocket = new Socket(hostName, portNumber);

        // Stream writer to the socket
        PrintWriter out =
                new PrintWriter(echoSocket.getOutputStream(), true);
        // Stream reader from the socket
        BufferedReader in =
                new BufferedReader(
                        new InputStreamReader(echoSocket.getInputStream()))
) {
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            try {
                // Query the server.
                out.println("?");
                // read response from the socket
                String receivedText = in.readLine(); // ** error here
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }, 1000, 1000);

这是服务器套接字:

while (((receivedText = in.readLine()) != null)) {
    if (receivedText.equals("?")) {
        out.println(getCurrentState());
    }
}

// close the connection socket
connectSocket.close();

但是,如果我使用while(true)和Thread.sleep(1000)而不是TimerTask,它可以工作。

2 个答案:

答案 0 :(得分:1)

问题在于,将BufferedReader in放入try - 资源块后,您的BuferedReader会在" main"之后立即自动关闭。线程离开try块的主要部分。这是在调用timer.schedule()之后发生的。因此,通过调用Timer启动的timer.schedule()线程稍后会在触发仅关闭的套接字/文件描述符时看到。

答案 1 :(得分:1)

TimerTask在一个单独的线程中运行,并且如here所述,虽然Socket是线程安全的,但不建议使用多个线程同时读/写Socket连接。

所以,在上面的例子中,Socket和BufferedReader都应该是任务的本地,如下所示:

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        try (
                // create TCP socket for the given hostName, remote port
                // PortNumber
                Socket echoSocket = new Socket(hostName, port);
                // Stream writer to the socket
                PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
                // Stream reader from the socket
                BufferedReader in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));) {
            // Query the server.
            out.println("?");
            // read response from the socket
            String receivedText = in.readLine(); // ** error here
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}, 1000, 1000);