我正在开发MTG / Hearthstone类型的纸牌游戏,但是服务器与客户端之间的通信出现问题。
我已经看过教程和项目,但是它们还没有帮助。客户端经常崩溃,或者在Controller中设置不正确。
服务器:
package server;
import game.GameData;
import game.PlayerData;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ServerTest implements Runnable {
private int port;
private boolean running, gameStarted;
private ArrayList<Socket> players;
private GameData gameData;
public ServerTest(int port){
this.port = port;
this.running = false;
this.gameStarted = false;
gameData = new GameData();
}
public Socket waitForConnection(ServerSocket serverSocket) {
try {
Socket socket = serverSocket.accept();
PlayerData playerData = readData(socket);
System.out.println("Player connected: " + playerData.getName());
gameData.getPlayers().add(playerData);
sendData(socket, playerData);
return socket;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public PlayerData readData(Socket socket){
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
return (PlayerData) objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void sendData(Socket socket, PlayerData playerData){
try {
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(playerData);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
running = false;
}
@Override
public void run() {
running = true;
int counter = 0;
try {
ServerSocket serverSocket = new ServerSocket(port);
players = new ArrayList<Socket>();
while (running) {
if(!gameStarted) {
if (gameData.getPlayers().size() < 2) {
players.add(waitForConnection(serverSocket));
}
if (gameData.getPlayers().size() == 2) {
gameData.drawCards();
gameData.getPlayers().get(0).setOpponent(gameData.getPlayers().get(1));
gameData.getPlayers().get(1).setOpponent(gameData.getPlayers().get(0));
gameData.getPlayers().set(0, readData(players.get(0)));
gameData.getPlayers().set(1, readData(players.get(1)));
sendData(players.get(0), gameData.getPlayers().get(0));
sendData(players.get(1), gameData.getPlayers().get(1));
gameStarted = true;
gameData.getPlayers().get(0).setStarted(true);
gameData.getPlayers().get(1).setStarted(true);
System.out.println("Game started");
}
} else {
Thread.sleep(500);
gameData.getPlayers().set(0, readData(players.get(0)));
gameData.getPlayers().set(1, readData(players.get(1)));
gameData.getPlayers().get(0).setOpponent(gameData.getPlayers().get(1));
gameData.getPlayers().get(1).setOpponent(gameData.getPlayers().get(0));
sendData(players.get(0), gameData.getPlayers().get(0));
sendData(players.get(1), gameData.getPlayers().get(1));
/*
sendData(players.get(counter), gameData.getPlayers().get(counter));
gameData.getPlayers().set(counter, readData(players.get(counter)));
if(counter == 0) {
gameData.getPlayers().get(1).setOpponent(gameData.getPlayers().get(0));
sendData(players.get(1), gameData.getPlayers().get(1));
counter = 1;
} else {
gameData.getPlayers().get(0).setOpponent(gameData.getPlayers().get(1));
sendData(players.get(0), gameData.getPlayers().get(0));
counter = 0;
}*/
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户:
package client;
import game.GameData;
import game.PlayerData;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientTest implements Runnable{
private int port;
private String host;
private PlayerData playerData;
private GameData gameData;
private Socket socket;
private boolean running;
public ClientTest(int port, String host, String name) {
this.port = port;
this.host = host;
playerData = new PlayerData(name);
running = false;
}
public void connectToServer(){
try {
socket = new Socket(host, port);
sendPlayerData(socket, playerData);
readGameData(socket);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void disconnectFromServer(){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendPlayerData(Socket socket, PlayerData playerData){
try {
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(playerData);
outputStream.flush();
} catch (IOException e) {
disconnectFromServer();
}
}
public PlayerData readGameData(Socket socket){
try {
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
return (PlayerData) inputStream.readObject();
} catch (Exception e) {
disconnectFromServer();
} return null;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public PlayerData getPlayerData() {
return playerData;
}
public void setPlayerData(PlayerData playerData) {
this.playerData = playerData;
}
public GameData getGameData() {
return gameData;
}
public void setGameData(GameData gameData) {
this.gameData = gameData;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
running = true;
connectToServer();
while (running){
while (!playerData.isStarted()) {
sendPlayerData(socket, playerData);
readGameData(socket);
}
//sendPlayerData(socket, playerData);
System.out.println("Read...");
PlayerData data;
while ((data = readGameData(socket)) != null) {
playerData = data;
}
}
}
}
这是我在控制器中设置PlayerData的方式:
public void setLoginData(String name, String ip, int port){
Platform.runLater(() -> {
client = new ClientTest(port, ip, name);
System.out.println(client.getPlayerData().getName());
Thread inputThread = new Thread(client);
inputThread.start();
myName.setText(client.getPlayerData().getName());
});
}
我希望服务器首先设置两个播放器,然后等待第一个客户端发送数据并为两个播放器设置新数据。
谢谢!