2016-02-29 56 views
1

我有一個套接字到服務器。在TimerTask的幫助下,每隔1秒查詢服務器並通過輸出/輸入流讀取響應。但是,我收到錯誤套接字已關閉套接字從TimerTask.run()中關閉

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(); 

但是,如果我用,而(真)和了Thread.sleep(1000),而不是TimerTask的的,它的工作原理。

回答

1

的問題是,把你的BufferedReader intry -with資源阻止你BuferedReader自動關閉「主」線程離開try塊的主要部分之後。這發生在撥打timer.schedule()之後。因此,通過調用timer.schedule()啓動的Timer線程因此在稍後觸發時僅觸發封閉的套接字/文件描述符。

1

TimerTask在單獨的線程中運行,並且如解釋here所示,雖然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);