我有一个 Java 客户端,它每 33 毫秒不断更新我的游戏程序中的一个类。问题是当我打开两个接收相同类并且应该同步的客户端时,它们会根据谁首先开始或与服务器联系而产生不同的结果。然后在值永远不会改变但我(现在)知道服务器正在向两者发送写入类之后。在我的导师讲义中,它说要这样做
ObjectInput input;
input = new ObjectInputStream(socket.getInputStream());
serializableobject = (cast) input.readObject();
input.flush();
这就是我被教导的方式,但现在我来实施它(在大学不需要这个)它不起作用。我花了数周和数月的时间试图找出原因,今天我认为我破解了原因,但不知道如何解决它。基本上从开始 input.flush(); ObjectInput 或 ObjectInputStream 似乎不存在,因此我将其排除在外并对其进行了测试,并且使用断点验证了我的服务器类已发送并设置了我的游戏设置类的所有变量,我的类显示得很可爱。问题出现在服务器上此类的下一次更新中,但我花了很长时间才解决。我相信正在发生的事情(如果我不放弃的话)是它读取发送的第一个对象并将其保存在输入流中。然后,当我调用相同的方法时,它会不断地给我第一个对象。我假设这是因为我没有像我的导师在讲座幻灯片中所说的那样冲洗它。输出流有一个我使用的冲洗。我还查看了 ObjectInput 和 ObjectInputStream ,并且无法看到刷新或替代方法或移动到流中下一个对象的方法。无论如何,我认为后者不是一个好主意,因为流只会持续增长,直到我假设内存可能耗尽。无论如何继承我的接收类和我的服务器。:无论如何,我认为后者不是一个好主意,因为流只会持续增长,直到我假设内存可能耗尽。无论如何继承我的接收类和我的服务器。:无论如何,我认为后者不是一个好主意,因为流只会持续增长,直到我假设内存可能耗尽。无论如何继承我的接收类和我的服务器。:
import java.io.*;
import java.net.*;
import java.util.*;
public class BaseServer
{
private String result = null;
//for serializable class input stream
ObjectInput input;
// Declare client socket
Socket clientSocket = null;
// Declare output stream and string to send to server
DataOutputStream os = null;
// Declare input stream from server and string to store input received from server
BufferedReader is = null;
String responseLine;
//get ip
String serverAddress ;
// Create a socket on port 5000 and open input and output streams on that socket
public void setUpNetwork(String serverAd)
{
try
{
serverAddress = serverAd;
clientSocket = new Socket(serverAddress, 5000);
//string
os = new DataOutputStream(clientSocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//serial
input = new ObjectInputStream( clientSocket.getInputStream() );
}
catch (UnknownHostException e)
{
System.err.println("Don't know about host: hostname");
}
catch (IOException e)
{
System.err.println("Couldn't get I/O for the connection to: hostname");
}
}
/*
* Used to communicate with server
* takes message to send and the object expecting the response
* 1 simple method to replace all but one of the below v1 methods
*/
public BaseSerialDataObjects serverTalk(String message){
sendStringMessage(message);
try {
BaseSerialDataObjects bSO = (BaseSerialDataObjects) input.readObject();
return bSO;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
////////Old v.1 methods for interacting with servers. I have now changed my mind
//and am using strings to send messages and serializable objects as return messages
//I have left these in as I have plans to reuse the most of the code in this game
public String read(){
// Write data to the socket
if (clientSocket != null && os != null && is != null)
{
try
{
os.writeBytes("ok \n");
return is.readLine(); // my bit
}
catch (UnknownHostException e)
{
System.err.println("Trying to connect to unknown host: " + e);
}
catch (IOException e)
{
System.err.println("IOException: " + e);
}
}
return responseLine;
}
//Sends messages to the server
public void sendStringMessage(String message){
// Write data to the socket
if (clientSocket != null && os != null && is != null){
try {
os.writeBytes( message + "\n" );
}
catch (UnknownHostException e){
System.err.println("Trying to connect to unknown host: " + e);
}
catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
/*
* V.1 method idea am leaving in for an option in future games
*/
public String getStringResult(String returnMessage)
{
String tempHolder = read();
if(tempHolder!=null)
{
String[] array = tempHolder.split("\\s+");
if(array[0].trim().equalsIgnoreCase(returnMessage))
{
result = null;
tempHolder = "";
for(int i = 1; i < array.length;i++)
{
tempHolder = tempHolder + array[i] + " ";
}
return tempHolder.trim();
}
else return null;
}
else
{
return null;
}
}
public synchronized void setResult(String res)
{
result = res;
}
public void closeConnections()
{
// Close the input/output streams and socket
try{
os.close();
is.close();
clientSocket.close();
}catch(Exception e)
{
System.err.println("Exception: " + e);
}
}
}
该行:BaseSerialDataObjects bSO = (BaseSerialDataObjects) input.readObject();
是我在下面的返回 bSO 行上放置断点的地方,它总是显示一个与第一个具有相同值的类,即使我只是在服务器上放置断点并在返回使客户端的类之前检查了它的不同值在我检查它时挂起,这样我就知道它是正确的线程和类以及所有内容
服务器 :
import java.io.*;
import java.net.*;
import java.*;
import java.util.regex.*;
public class TCPserver implements Runnable
{
static Socket server = null;
private static final int possibleNumberOfPlayers = 8;
private static final int amountOfPlayerInfoHeld = 6;
private int threadNumber;
private static ServerSettings gameSettings = new ServerSettings();
private static int numberOfSettings = 4;
//position 0 = name;
//position 1 = angle;
//position 2 = position x
//position 3 = position y
//position 4 = state
//position 5 = state in relation to server
//POssible states:
// connected
static PlayerPositionsSerial positions = new PlayerPositionsSerial();
public static void main( String args[] )
{
positions.playersArray = new String [possibleNumberOfPlayers][amountOfPlayerInfoHeld];
// Declare a server socket and a client socket for the server
ServerSocket service = null;
// Try to open a server socket on port 5000
try
{
service = new ServerSocket(5000);
server = service.accept();
Thread t0 = new Thread (new TCPserver(0));
t0.start();
server = service.accept();
Thread t1 = new Thread (new TCPserver(1));
t1.start();
server = service.accept();
Thread t2 = new Thread (new TCPserver(2));
t2.start();
server = service.accept();
Thread t3 = new Thread (new TCPserver(3));
t3.start();
server = service.accept();
Thread t4 = new Thread (new TCPserver(4));
t4.start();
server = service.accept();
Thread t5 = new Thread (new TCPserver(5));
t5.start();
server = service.accept();
Thread t6 = new Thread (new TCPserver(6));
t6.start();
server = service.accept();
Thread t7 = new Thread (new TCPserver(7));
t7.start();
/*server = service.accept();
Thread t8 = new Thread (new TCPserver(8));
t8.start(); */
}
catch (IOException e)
{
System.out.println(e + "Error B");
}
}
public void run()
{
// Declare an input stream and String to store message from client
BufferedReader is;
String line;
// Declare an output stream to client
DataOutputStream os;
String thr = Integer.toString(threadNumber);
// Create a socket object from the ServerSocket to listen and accept
// connections. Open input and output streams
try
{
ObjectOutput output;
output = new ObjectOutputStream( server.getOutputStream() );
is = new BufferedReader( new InputStreamReader(
server.getInputStream()));
//if( (line = is.readLine()) != null )
while( (line = is.readLine()) != null )
{
if(line != null)
{
switch(rules(line)){
case "playertable":
output.writeObject( positions );
break;
case "gamesettings":
output.writeObject( gameSettings );
break;
case "servernumber":
StringReturnSerial string = new StringReturnSerial();
string.s = Integer.toString(threadNumber);
output.writeObject(string);
break;
default:
System.out.println("line didnt select anything");
break;
}
}output.flush();
}
// Comment out/remove the stream and socket closes if server is to remain live.
is.close();
}
catch (IOException e)
{
System.out.println(e + "Error B");
}
}
public TCPserver(int tNumber)
{
threadNumber = tNumber;
}
private synchronized void changeArray(int row, int col, String value)
{
positions.playersArray[row][col] = value;
}
private synchronized String readArray(int row, int col)
{
return positions.playersArray[row][col];
}
private String rules(String lineIn)
{
try {
String[] splitArray = lineIn.split("\\s+");
switch(splitArray[0])
{
case "SIGNIN":
positions.playersArray[threadNumber][0] = splitArray[1];
positions.playersArray[threadNumber][4] = "normal";
positions.playersArray[threadNumber][amountOfPlayerInfoHeld-1] = "connected";
addPlayer();
gameSettings.gameStartTime = System.currentTimeMillis() + 10000;
return "gamesettings";
case "ok":
// just for reply, do nothing response heard "ok"
break;
case "MATCHMAKE":
positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "matchmake";
gameSettings.gameState = "matchmake";
return "playertable";
case "READY":
positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "ready";
return "gamesettings";
case "REQUESTSTART":
boolean goAhead = true;
for(int i = 0 ; i < gameSettings.numberOfConnectedPlayers; i++)
{
if(positions.playersArray[i][amountOfPlayerInfoHeld-1] != "ready")
{
goAhead = false;
}
}
if(goAhead)
{
long start = System.currentTimeMillis( );
start = start + 10000;
gameSettings.gameStartTime = start;
}
return "gamesettings";
case "GETPOS":
return "playertable";
case "UPDATEPOS":
//heres where to notice crashes and check for wins etc...
positions.playersArray[threadNumber][1] = splitArray[1];
positions.playersArray[threadNumber][2] = splitArray[2];
positions.playersArray[threadNumber][3] = splitArray[3];
positions.playersArray[threadNumber][4] = splitArray[4];
return "playertable";
case "GETSETTINGS":
return "gamesettings";
/*case "SENDSETTINGS":
// updates settings
for (int i = 1; i < splitArray.length; i++){
switch(i){
case 1:
gameSettings.gameState = splitArray[i];
break;
case 2:
gameSettings.winningNumberOfLaps = Integer.parseInt(splitArray[i]);
break;
case 3:
gameSettings.winString = splitArray[i];
break;
case 4:
gameSettings.gameStartTime = Long.parseLong(splitArray[i]);
break;
case 5:
gameSettings.numberOfConnectedPlayers = Integer.parseInt(splitArray[i]);
break;
}
}
returnString = "gamesettings";
break;
*/
case "GETSERVERNUMBER":
return "servernumber";
case "PLAYING":
gameSettings.gameState = "playing";
break;
case "SERVERPLAYERSTATEUPDATE":
int crashed = 0;
positions.playersArray[Integer.parseInt(splitArray[1])][5] = splitArray[2];
for(int i = 0; i < gameSettings.numberOfConnectedPlayers;){
//takes into account possibility of people leaving game
if(positions.playersArray[i][5] != null){
if(positions.playersArray[i][5] == "explode"){
crashed++;
}
}
}
if(crashed == gameSettings.numberOfConnectedPlayers)
gameSettings.gameState = "explode";
return "gamesettings";
default:
System.err.println("Rule Not Found: " + splitArray[0]);
break;
}
} catch (PatternSyntaxException ex) {
System.err.println("error C: " + ex);
}
return null;
}
public synchronized void addPlayer()
{
gameSettings.numberOfConnectedPlayers++;
}
public synchronized int getNumberOfPlayers()
{
return gameSettings.numberOfConnectedPlayers;
}
public synchronized void removePlayer()
{
gameSettings.numberOfConnectedPlayers--;
}
}
提前感谢约翰哈里斯