我有一个多人游戏。 我已经运行了一个java套接字服务器程序。
我发送字符串到socketserver,收到的很好。
这是我的发送和接收课程:
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, BaseSerialDataObjects serializableobject){
sendStringMessage(message);
try {
switch(serializableobject.getClass().getSimpleName()){
case "PlayerPositionsSerial":
PlayerPositionsSerial serializableobject2 = (PlayerPositionsSerial) input.readObject();
return serializableobject2;
case "GameSettings":
return serializableobject = (GameSettings) input.readObject();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//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);
}
}
}
在serverTalk()方法的两个return语句中程序完全冻结但似乎没有崩溃我不知道发生了什么?
我的讲师在讨论这个话题时说:
ObjectInput input;
input = new ObjectInputStream( socket.getInputStream() );
serializableobject = ( cast ) input.readObject();
input.flush();
输入刷新位不起作用,我不知道为什么它是必要的。 当我尝试在输入中包含其标记并建议我将其转换为输出流
我试图移动的类在服务器和客户端上是相同的:
import java.io.Serializable;
public class BaseSerialDataObjects implements Serializable{
}
/*
* class for game settings
* decided to split it and make it serializable incase of multi player
* thought this would be easier to standardise setting across multiple devices
*/
public class GameSettings extends BaseSerialDataObjects{
//GameWide variables
public String gameState;
public int winningNumberOfLaps = 1;
public String winString;
public long gameStartTime;
}
/*
* this class will be used on the server and each player will on request
* Receive a copy with player information
*/
public class PlayerPositionsSerial extends BaseSerialDataObjects {
//position 0 = name;
//position 1 = angle;
//position 2 = position x
//position 3 = position y
//position 4 = state
//position 5 = state in relation to server
public String[][] playersArray;
}
我真的很失望,我确实有一套非常乏味的字符串前后回复,并认为只要求这些信息就会让所有东西都更容易管理
服务器代码只是包含:
public class TCPserver implements Runnable
{
static Socket server = null;
static String gameState = "menu";
static int numberOfConnectedPlayers = 0;
private static final int possibleNumberOfPlayers = 8;
private static final int amountOfPlayerInfoHeld = 6;
private int threadNumber;
private static GameSettings gameSettings = new GameSettings();
//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);
}
}
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)
{
line = rules(line);
switch(line){
case "playertable":
output.writeObject( positions );
break;
case "gamesettings":
output.writeObject( gameSettings );
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);
}
}
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)
{
String returnString = "";
try {
String[] splitArray = lineIn.split("\\s+");
switch(splitArray[0])
{
case "signIn":
positions.playersArray[threadNumber][0] = splitArray[1];
positions.playersArray[threadNumber][amountOfPlayerInfoHeld-1] = "connected";
addPlayer();
returnString = "gamesettings ";
break;
case "ok":
// just for reply, do nothing response heard "ok"
break;
case "matchMake":
positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "matchmake";
gameSettings.gameState = "matchmake";
returnString = "playertable";
break;
case "ready":
positions.playersArray[threadNumber][amountOfPlayerInfoHeld -1] = "ready";
returnString = "gamesettings";
break;
case "requestStart":
boolean goAhead = true;
for(int i = 0 ; i < numberOfConnectedPlayers; i++)
{
if(positions.playersArray[i][amountOfPlayerInfoHeld-1] != "ready")
{
goAhead = false;
}
}
if(goAhead)
{
long start = System.currentTimeMillis( );
start = start + 10000;
gameSettings.gameStartTime = start;
}
returnString = "gamesettings";
break;
case "getPos":
returnString = splitArray[0] + " ";
returnString = "playertable";
break;
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];
returnString = "playertable";
break;
}
} catch (PatternSyntaxException ex) {
System.err.println("error: " + ex);
}
return returnString;
}
public synchronized void addPlayer()
{
numberOfConnectedPlayers++;
}
public synchronized int getNumberOfPlayers()
{
return numberOfConnectedPlayers;
}
public synchronized void removePlayer()
{
numberOfConnectedPlayers--;
}
}
对此的任何帮助都将受到大力赞赏,谢谢
答案 0 :(得分:0)
对您的问题最直接的解释是服务器根本不响应,这使客户端永远等待(input.readObject()
将等待直到收到一些数据)。在您的服务器代码中,您应该确保实际上是在回答客户端:
switch(line){
case "playertable":
output.writeObject( positions );
break;
case "gamesettings":
output.writeObject( gameSettings );
break;
default:
// You should throw an exception or output an error message here
}
一个问题可能是是服务器代码的另一部分:
returnString = "gamesettings ";
由于额外的空间而与case "gamesettings"
不匹配。
答案 1 :(得分:0)
您在同一底层套接字输入流上使用多种输入stread / reader。由于缓冲中至少有两个是缓冲的,因此缓冲将“窃取”来自其他流的数据。如果你想使用对象序列化,请将它用于所有事情:摆脱DataInputStream
和BufferedReader
,以及在发送端写入数据的任何内容,只需使用ObjectInputStream
和{ {1}}。