2

我有一个多人游戏。我有一个已经在运行的 java 套接字服务器程序。

我将字符串发送到接收良好的套接字服务器。

这是我的发送和接收类:

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() 方法中的两个返回语句中,程序完全冻结但似乎没有崩溃我不知道发生了什么?

我的讲师在解释这个话题时说:

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--;
}
}

对此的任何帮助将不胜感激,谢谢

4

2 回答 2

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"由于额外的空间,这与您的不匹配。

于 2013-06-25T14:13:38.653 回答
0

您在同一个底层套接字输入流上使用多种输入跨步/读取器。由于其中至少有两个被缓冲,这不可能工作,因为缓冲将从其他流中“窃取”数据。如果您想使用对象序列化,请将其用于所有内容:摆脱DataInputStreamBufferedReader,以及在发送端写入该数据的任何内容,而只需使用ObjectInputStreamand ObjectOutputStream

于 2013-06-26T09:58:13.527 回答