2013-05-06 198 views
1

我與的readLine()在Java中的一個問題。我有一臺服務器和一個客戶端。從客戶端我想發送消息到服務器。問題是,首先,客戶端必須將文本插入到JTextField中,然後當按下發送服務器以從客戶端讀取輸入時,但服務器不會等待來自客戶端的輸入,而是讀取空值。但是我讀了readLine()被阻塞,直到它有東西可讀,爲什麼在這種情況下不會發生?java.io.BufferedReader.readLine()是非阻塞

在這裏,我連接到服務器並創建的JFrame

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

import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class StartingPoint { 

private static PrintWriter out; 
private static BufferedReader in; 

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       connectToServer(); 
       createAndShowGui(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

public static void createAndShowGui() throws IOException { 
    View frame = new View(out, in); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setLocationByPlatform(true); 
    frame.setVisible(true); 
} 

public static void connectToServer() throws IOException { 
    String serverAddress = "127.0.0.1"; 

    int PORT = 8100; 

    Socket clientSocket = null; 
    out = null; 
    in = null; 

    try { 
     clientSocket = new Socket(serverAddress, PORT); 
     out = new PrintWriter(clientSocket.getOutputStream(), true); 
     in = new BufferedReader(new InputStreamReader(
       clientSocket.getInputStream())); 
    } catch (UnknownHostException e) { 
     System.err.println("Could not connect to the server \n" + e); 
     System.exit(1); 
    } finally { 
     if (out != null) 
      out.close(); 
     if (in != null) 
      in.close(); 
     if (clientSocket != null) 
      clientSocket.close(); 
    } 
} 
} 

這裏是JFrame中實現:

import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.PrintWriter; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextField; 

public class View extends JFrame { 

private JButton button; 
private JTextField field; 
private JPanel gui; 

public View(final PrintWriter out, final BufferedReader in) throws IOException { 

    button = new JButton("Send"); 
    field = new JTextField(); 

    gui = new JPanel(new GridLayout(1, 0, 10, 10)); 

    gui.add(button); 
    gui.add(field); 

    add(gui); 

    button.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      out.println(field.getText()); 

      try { 
       System.out.println(in.readLine()); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 
} 

這裏是服務器:

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

public class SimpleServer extends Thread { 

public static final int PORT = 8100; 
private static ServerSocket serverSocket = null; 

private Socket clientSocket = null; 

public void run() { 
    String receive, answer; 
    try { 
     BufferedReader in = new BufferedReader(new InputStreamReader(
       clientSocket.getInputStream())); 

     PrintWriter out = new PrintWriter(clientSocket.getOutputStream()); 

     receive = in.readLine(); 
     System.out.println("[server]" + receive); 
     answer = "hello " + receive; 
     out.println(answer); 
     out.flush(); 

    } catch (IOException e) { 
     System.err.println("IO error \n" + e); 
    } finally { 
     try { 
      clientSocket.close(); 
     } catch (IOException e) { 
      System.err.println("Close socket error \n" + e); 
     } 

    } 
} 

public SimpleServer() throws IOException { 

    while (true) { 
     serverSocket = new ServerSocket(PORT); 
     try { 
      clientSocket = serverSocket.accept(); 

      new Thread(this).start(); 

     } finally { 
      serverSocket.close(); 
     } 
    } 
} 

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

回答

6

您的connectToServer()方法打開一個連接,創建流並...然後在返回之前關閉它們。所以當然,服務器立即看到關閉,並在第一個readLine()調用返回null


我懷疑你可能已經複製了「close in finally blocks」模式而不明白它的意思。所以,我會解釋:

這是正常的模式:

InputStream is = null; 
try { 
    is = new FileInputStream(someFile); 
    // read the stream 
} finally { 
    if (is != null) { 
     is.close(); 
    } 
} 

上面的代碼的目的是爲了確保InputStream的始終是關閉的。或者更確切地說,在嘗試/最終退出之前它總是關閉

這通常是一件好事。但是,如果你的代碼的目的是打開一些在這段代碼完成後將要使用的流,那麼關閉這個流是自我失敗的。

InputStream is = null; 
try { 
    is = new FileInputStream(someFile); 
} finally { 
    if (is != null) { 
     is.close(); 
    } 
} 
// read the stream ... OOOPS! We've already closed it!! 

所以藉此回到你原來的代碼,你需要在try /終於/關閉的東西移到run方法,沿着這些路線的東西:

public void run() { 
     try { 
      connectToServer(); 
      createAndShowGui(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (out != null) 
       out.close(); 
      if (in != null) 
       in.close(); 
      if (clientSocket != null) 
       clientSocket.close(); 
     } 
    } 

你應該也趕上和(可能)忽略IOException,可能會被每個close()調用拋出。

2

Javadoc文檔BufferedReader.readLine() 沒有按不要這樣說:

返回: 包含行的內容,不包括 任何行終止符,則返回null流的末尾已到達

在你的代碼String你在connectToServer()中打開一個連接並關閉它,所以服務器看到流的末尾