通过套接字发送对象时,Java客户端应用程序冻结

时间:2012-03-15 21:01:43

标签: java sockets object stream

我有这个客户端/服务器应用程序,当我尝试通过套接字发送对象时,客户端应用程序有时会完全冻结

public Client client = new Client();
petriNetList = client.query(client.actionLoadPetriNetList, MainWindow.loginUsername);

这是客户端的代码

 public class Client {
    public static Socket kkSocket = null;
    public static PrintWriter out = null;
    public static BufferedReader in = null;
    public static BufferedReader stdIn = null;
    public static OutputStream outputStream = null ;
    public static ObjectOutputStream  objectOutputStream = null ; 
    public static InputStream inputStream = null ; 
    public static ObjectInputStream  objectInputStream = null ;  


    public String actionSavePetriNet = "SAVE PETRI NET START";



    /*
     * Save petri net to server
     * 
     * @param action identifies query
     * @param petriName name of the petri net
     * @param username username
     * @param xml content of the petri net
     * 
     * @return int response form server
     */
public int query (String action,String petriName,String username,String xml) throws IOException {



    int size ;
    int result = 0;
    connect();
    if (action.equals(actionSavePetriNet)) {

        out.println(action); // save petri net
        out.println(petriName); //petri net name
        out.println(username); //username
        System.out.println("(Client:)" + xml);
        objectOutputStream.writeObject(xml); //send object over the network
        System.out.println("Dostali sme sa sem ?");
        result = Integer.parseInt(in.readLine()); //read response from server
    }

       disconnect();
        return result;
}    


    /*
     * connect to server
     * TODO: ADD hostname and port as parameter
     */
    public static void connect() throws IOException {
    try {
            kkSocket = new Socket("osiris-PC", 4444);
            out = new PrintWriter(kkSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: taranis.");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: taranis.");
            System.exit(1);
        }

         stdIn = new BufferedReader(new InputStreamReader(System.in));

          outputStream = kkSocket.getOutputStream();  
          objectOutputStream = new ObjectOutputStream(outputStream);  

          inputStream = kkSocket.getInputStream();
          objectInputStream = new ObjectInputStream(inputStream);

    }

    /*
     * Disconnect from server
     * close all input/output streams
     * 
     */
    public static void disconnect() throws IOException {
        out.close();
        in.close();
        stdIn.close();
        objectOutputStream.close();
        outputStream.close();
        objectInputStream.close();
        inputStream.close();
        kkSocket.close();

    }
}

这是服务器的代码

public class PetriServer {
    public static Protocol kkp = new Protocol();

    public static   InputStream inputStream = null ;
    public static   ObjectInputStream objectInputStream = null ; 
    public static   OutputStream outputStream = null ;
    public static   ObjectOutputStream objectOutputStream = null ;



    public static void main(String[] args) throws IOException, ClassNotFoundException {
        kkp.loadUsers();

     while(true) {
         ServerSocket serverSocket = null;

            inputStream = null ;
            objectInputStream = null ; 
            outputStream = null ;
            objectOutputStream = null ;

        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 4444.");
            System.exit(1);
        }

        Socket clientSocket = null;
        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }

        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(
                new InputStreamReader(
                clientSocket.getInputStream()));

        inputStream = clientSocket.getInputStream();  
       objectInputStream = new ObjectInputStream(inputStream);  

        outputStream = clientSocket.getOutputStream();
       objectOutputStream = new ObjectOutputStream(outputStream);
       inputLine = in.readLine();

        String inputLine;
 if (inputLine.equals("SAVE PETRI NET START")) {

            String petriName;
            String username;
            String xml ;
            String input;
            int result;
            int size ;

            petriName = in.readLine(); //read petri name

            System.out.println("(Server): prijali sme poziadavok na ulozenie " + petriName );


            username = in.readLine(); //read username
            System.out.println("(Server): poziadavok ide od usera: " + username);

          while(true) {

//this is the line where is occasionally freezes 
                xml = (String)objectInputStream.readObject(); //read object over the network
           if (!xml.isEmpty()) break; 
          }


          System.out.println("(Server):" + xml);

            result = kkp.savePetrinet(username, petriName,xml); //save it to the file
            out.println(result);

        }

        out.close();
        in.close();
        objectInputStream.close();
        inputStream.close();
        objectOutputStream.close();
        outputStream.close();
        clientSocket.close();
        serverSocket.close();


    }
    }
}

有人知道会出现什么问题吗? 欢呼声。

1 个答案:

答案 0 :(得分:1)

服务器上的Socket InputStream连接到两个不同的输入ObjectInputStreamBufferedReaderInputStreams不打算以这种方式使用,这样做会导致很多问题。 BufferedReaders,就其本质而言,将从InputStream中提取的数据超过您实际阅读的数据。如果它们恰好缓冲构成对象的数据,那么随后尝试从ObjectInputStream读取对象将会阻止,因为数据已被删除。

您需要选择一种方法或另一种方法来读取数据。如果你需要能够从套接字读取字符串和对象,那么你将不得不进入面向字节的操作模式,你将字节读入字节数组,然后自己处理字节数组以确保你没有丢失任何数据。

根据以下@Dunes评论进行编辑

似乎你最好的选择是完全坚持使用ObjectInputStream并使用其他方法来允许你从流中读取任意基本类型。而且,如果你不介意弃用的电话,它甚至有一个readLine方法。