這一定很容易,但我顯然缺少一些基本的理解。 我有簡單的客戶端服務器應用程序Java:client-sever app.- WHILE on ObjectInputStream讀取線程
服務器:
public class GameServer{
private Socket clientSocket;
private ServerSocket serverSocket;
private ArrayList<ObjectOutputStream> oosPlayers=new ArrayList<ObjectOutputStream>();
public static void main(String args[]){
GameServer server = new GameServer();
server.startGame();
}
public void startGame(){
try{
serverSocket = new ServerSocket(10008);
System.out.println("Server started at:" + serverSocket);
while(true){
System.out.println("Server: Waiting for client requests...");
clientSocket=serverSocket.accept();
System.out.println("Server: Client connection accepted at:"+clientSocket);
//remember player's output stream
oosPlayers.add(new ObjectOutputStream(clientSocket.getOutputStream()));
//read data from clients
Thread receiverThread = new Thread(new DataReceiver());
receiverThread.start();
}
}
catch(IOException ex){
System.out.println(ex.getMessage());
}
}
public class DataReceiver implements Runnable{
public void run(){
try{
String mess;
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
while((mess=(String)ois.readObject()) != null){
System.out.println("Server: "+mess);
send();
}
}
catch(Exception ex){ System.out.println(ex.getMessage()); }
}
public void send(){
for (ObjectOutputStream oos : oosPlayers){
try{
oos.writeObject(new String("There is "+oosPlayers.size()+" player(s) at the board"));
oos.flush();
}
catch(Exception ex){ System.out.println(ex.getMessage()); }
}
}
}
}
客戶端:
public class GameClient implements ActionListener{
private Socket socket;
private ObjectInputStream ois;
private ObjectOutputStream oos;
private JButton button;
public static void main(String args[]){
GameClient client = new GameClient();
client.drawBoard();
}
public void drawBoard(){
JFrame frame = new JFrame("A game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("Send");
button.addActionListener(this);
configureConnection();
Thread receiverThread = new Thread(new DataReceiver());
receiverThread.start();
frame.getContentPane().add(new JPanel().add(button));
frame.setSize(200,200);
frame.setVisible(true);
}
public void configureConnection(){
try{
socket = new Socket("127.0.0.1", 10008);
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
}
catch(Exception ex) { System.out.println(ex.getMessage()); }
}
public void actionPerformed(ActionEvent ev){
if (ev.getSource()==button){
try{
oos.writeObject(new String("Some data from client"));
oos.flush();
}
catch(Exception ex){ System.out.println(ex.getMessage()); }
}
}
public class DataReceiver implements Runnable{
public void run(){
try{
String mess;
while((mess=(String)ois.readObject())!= null){
System.out.println("Client:"+mess);
}
}
catch(Exception ex){ System.out.println(ex.getMessage()); }
}
}
}
我的問題涉及到receiverThread兩側。當我在從ObjectInputStream(在RUN方法中)讀取時使用WHILE時,服務器偵聽客戶端請求,並將其正確地分派給所有ObjectOutputStream s。如果我將這個WHILE更改爲IF每個客戶端僅從服務器讀取(併發送)數據。這同樣適用於客戶的WHILE/IF。
我的理解是,當我運行receiverThread它以某種方式停止線程在WHILE並繼續讀輸入流,而使用IF讓線程完成(從而停止讀取過程)。儘管WHILE條件不滿足,即最初(沒有客戶端連接),但它如何保持receiverThread還活着。在receiverThread已經讀取數據並且流中沒有任何內容的情況下會發生同樣的情況。
希望對這個基本問題有一些解釋。
問候 馬辛
感謝您的回答。我仍然好奇,第一次'while((mess =(String)ois.readObject())!= null)'在服務器上執行時,條件失敗(流爲空),但它沒有退出運行方法並持續監聽輸入流。 –
它不會繼續監聽InputStream。它正在監聽* socket *,因爲您尚未關閉它。清除實現應該用try/finally塊封裝while循環,並在finally塊中關閉流。 – AlexR
這可能是不正確的,但我相信它不會退出'while((mess =(String)ois.readObject())!= null)',因爲你的套接字處於_blocking mode_中,並且讀線程會阻塞readObject()方法,直到它讀取數據或關閉套接字(這會導致引發Exception)。 –