I am wondering why it gets stuck on the following line, but it didn't used to get stuck when I was using a BufferedReader with an InputStreamReader:
input = new ObjectInputStream(socket.getInputStream());
Here is my client code:
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;
}
}
}
}
Here is my server code:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;
/** * A server for a network multi-player tic tac toe game. Modified and * extended from the class presented in Deitel and Deitel "Java How to * Program" book. I made a bunch of enhancements and rewrote large sections * of the code. The main change is instead of passing data between the * client and server, I made a TTTP (tic tac toe protocol) which is totally * plain text, so you can test the game with Telnet (always a good idea.) * The strings that are sent in TTTP are: * * Client -> Server Server -> Client * ---------------- ---------------- * MOVE (0 <= n <= 8) WELCOME (char in {X, O}) * QUIT VALID_MOVE * OTHER_PLAYER_MOVED * VICTORY * DEFEAT * TIE * MESSAGE * * A second change is that it allows an unlimited number of pairs of * players to play. */ public class 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();
}
}
}
/** * A two-player game. */ class Game {
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) {}
}
}
}
}
Straight from 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.
You need to construct the a ObjectOutputStream before the ObjectInputStream. Otherwise you get a deadlock because of the stream header written and read by the constructors.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.