这一定很容易,但我显然缺少一些基本的理解。 我有简单的客户端服务器应用程序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)。 –