我想知道为什么它会卡在以下行,但当我将 BufferedReader 与 InputStreamReader 一起使用时,它并没有卡住:
input = new ObjectInputStream(socket.getInputStream());
这是我的客户端代码:
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class MtgTestRunsClient {
private JFrame frame = new JFrame("MTG Test Runs");
private static int PORT = 8901;
private Socket socket;
//private BufferedReader inFromServer;
//private PrintWriter outToServer;
private ObjectInputStream inFromServer;
private ObjectOutputStream outToServer;
private Planeswalker planeswalker;
public MtgTestRunsClient(String serverAddress) throws Exception {
// Setup networking
socket = new Socket(serverAddress, PORT);
//inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//outToServer = new PrintWriter(socket.getOutputStream(), true);
inFromServer = new ObjectInputStream(socket.getInputStream());
outToServer = new ObjectOutputStream(socket.getOutputStream());
planeswalker = new BUGDelverPlaneswalker();
planeswalker.setOutputToServer(outToServer);
// Frame content
JPanel contentPane = new JPanel(new BorderLayout());
frame.setContentPane(contentPane);
frame.getContentPane().add(planeswalker.getStatusBar(), BorderLayout.SOUTH);
frame.getContentPane().add(planeswalker, BorderLayout.CENTER);
}
public void play() throws Exception {
//String response;
Object response;
try {
//response = inFromServer.readLine();
response = inFromServer.readObject();
if (response instanceof String ){
if( ((String)response).startsWith("WELCOME")) {
char mark = ((String)response).charAt(8);
frame.setTitle("MTG Test Runs - Player " + mark);
}
}
while (true) {
//response = inFromServer.readLine();
response = inFromServer.readObject();
if (response instanceof String ){
if (((String)response).startsWith("OPPONENT_MOVED")) {
planeswalker.getStatusBar().setStatusString("Opponent "+((String)response).substring(15), false, true);
} else if (((String)response).startsWith("GAME_OVER")) {
break;
} else if (((String)response).startsWith("MESSAGE")) {
String messageText = ((String)response).substring(8);
planeswalker.getStatusBar().setStatusString(messageText, false, true);
}
}else if(response instanceof Planeswalker){
planeswalker.setOpponent((Planeswalker)response);
}
}
outToServer.writeObject("QUIT");
outToServer.flush();
}
finally {
socket.close();
}
}
private boolean wantsToPlayAgain() {
int response = JOptionPane.showConfirmDialog(frame,
"Want to play again?",
"Tic Tac Toe is Fun Fun Fun",
JOptionPane.YES_NO_OPTION);
frame.dispose();
return response == JOptionPane.YES_OPTION;
}
/**
* Runs the client as an application.
*/
public static void main(String[] args) throws Exception {
while (true) {
String serverAddress = (args.length == 0) ? "localhost" : args[1];
MtgTestRunsClient client = new MtgTestRunsClient(serverAddress);
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setExtendedState(client.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
client.frame.setVisible(true);
client.frame.repaint();
client.play();
if (!client.wantsToPlayAgain()) {
break;
}
}
}
}
这是我的服务器代码:
导入java.io.BufferedReader; 导入java.io.IOException; 导入 java.io.InputStreamReader; 导入 java.io.ObjectInputStream; 导入 java.io.ObjectOutputStream; 导入 java.io.PrintWriter; 导入 java.net.ServerSocket; 导入java.net.Socket;
/** * 网络多人井字游戏的服务器。修改后的和 * 扩展自 Deitel 和 Deitel“Java How to *程序”书。我做了很多改进并重写了大部分内容 * 的代码。主要的变化是在之间传递数据 * 客户端和服务器,我做了一个TTTP(井字游戏协议(protocol)),这完全是 * 纯文本,这样您就可以使用 Telnet 测试游戏(总是一个好主意。) * TTTP 中发送的字符串是: * * 客户端->服务器服务器->客户端 * ---------------- ---------------- * MOVE (0 <= n <= 8) WELCOME ({X, O} 中的字符) * 退出有效移动 * OTHER_PLAYER_MOVED * 胜利 * 打败 * 领带 * 信息 * * 第二个变化是它允许无限数量的配对 * 玩家进行游戏。 */ 公共(public)类 MtgTestRunsServer {
/**
* Runs the application. Pairs up clients that connect.
*/
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(8901);
System.out.println("MTG Test Runs Server is Running");
try {
while (true) {
Game game = new Game();
Game.Player player1 = game.new Player(listener.accept(), '1');
Game.Player player2 = game.new Player(listener.accept(), '2');
player1.setOpponent(player2);
player2.setOpponent(player1);
game.currentPlayer = player1;
player1.start();
player2.start();
}
} finally {
listener.close();
}
}
}
/** * 两人游戏。 */ 类游戏{
Player currentPlayer;
public synchronized boolean legalMove(Player player, String move) {
if (player == currentPlayer ) {
currentPlayer = currentPlayer.opponent;
currentPlayer.otherPlayerMoved(move);
return true;
}
return false;
}
class Player extends Thread {
char playerNo;
Player opponent;
Socket socket;
//BufferedReader input;
//PrintWriter output;
ObjectInputStream input;
ObjectOutputStream output;
public Player(Socket socket, char playerNumber) {
this.socket = socket;
this.playerNo = playerNumber;
try {
//input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//output = new PrintWriter(socket.getOutputStream(), true);
output = new ObjectOutputStream(socket.getOutputStream());
output.writeObject("WELCOME " + playerNumber);
output.flush();
output.writeObject("MESSAGE Waiting for opponent to connect");
output.flush();
**input = new ObjectInputStream(socket.getInputStream());** // Must do this after constructed ObjectOutputStream above
//output.println("WELCOME " + playerNumber);
} catch (IOException e) {
System.out.println("Player died: " + e);
}
}
/**
* Accepts notification of who the opponent is.
*/
public void setOpponent(Player opponent) {
this.opponent = opponent;
}
/**
* Handles the otherPlayerMoved message.
*/
public void otherPlayerMoved(String move) {
//output.println("OPPONENT_MOVED " + move);
try {
output.writeObject("OPPONENT_MOVED " + move);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* The run method of this thread.
*/
public void run() {
try {
// The thread is only started after everyone connects.
//output.println("MESSAGE All players connected");
output.writeObject("MESSAGE All players connected");
output.flush();
// Tell the first player that it is her turn.
if (playerNo == '1') {
//output.println("MESSAGE Your move");
output.writeObject("MESSAGE Your move");
output.flush();
}
// Repeatedly get commands from the client and process them.
while (true) {
//String command = input.readLine();
Object command;
try {
command = input.readObject();
if(command instanceof String){
if (((String)command).startsWith("MOVE")) {
String move = ((String)command).substring(5);
if (legalMove(this, move)) {
//output.println("VALID_MOVE");
output.writeObject("VALID_MOVE");
} else {
output.writeObject("MESSAGE INVALID_MOVE");
//output.println("MESSAGE INVALID_MOVE");
}
} else if (((String)command).startsWith("QUIT")) {
return;
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println("Player died: " + e);
} finally {
try {socket.close();} catch (IOException e) {}
}
}
}
}
最佳答案
直接来自the javadoc :
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
关于java - 为什么我的 Java 客户端/服务器应用程序在使用 ObjectInputStream 时会挂起,但在将 BufferedReader 与 InputStreamReader 结合使用时却不会挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20716993/