首页 > 解决方案 > Android 中的 StreamCorruptedException

问题描述

所以我必须用 Android 客户端实现一个推荐系统。该系统的工作原理如下:用户将其位置和所需推荐的数量发送到服务器。然后服务器生成推荐并发送回推荐的 Pois(兴趣点)。

这是我的问题。当客户端从Pois[]服务器读取数组(实际推荐)时,StreamCorruptedException会抛出 a。奇怪的是,当我在自己的计算机上运行应用程序时,这从未发生过。只有当我在大学的计算机上运行它时才会发生这种情况。它并不总是发生。它可能会发生 8/10 次我运行它。

任何帮助将不胜感激。这是例外。

java.io.StreamCorruptedException: invalid type code: 3A
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java.1521)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1772)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1992)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1916)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream(1799)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)
    at java.io.ObjectInputStream.readUnshared(ObjectInputStream.java:463)
    at client.ds2018.ClientActivity$Fetcher.fetch(ClientActivity.java:283)
    at client.ds2018.ClientActivity$Fetcher.doInBackground(ClientActivity.java:311)
    at client.ds2018.ClientActivity$Fetcher.doInBackground(ClientActivity.java:256)
    at android.os.AsyncTask$2.call(AsyncTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java.1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)

这是代码。这是Poi课堂。这些数组作为响应发送给客户端。

public class Poi implements Serializable
{
    private int id; // Poi id
    private byte[] image; // Binary representation of location's image.
    private double latitude, longitude;
    private String name, category, imageURL; // The url address of the image.

    // Constructor, getters & setters[...]
}

这是ClientActivity类(客户端)。

public class ClientActivity extends AppCompatActivity implements OnMapReadyCallback
{
    private Fetcher f; // The async task that fetches the Pois.
    private Poi[] recs; // Recommendations array.
    private int uid, k; // User id and number of recommendations.

    private class Fetcher extends AsyncTask<Void, Void, Poi[]>
    {
        Poi poi;
        int k, uid;
        ProgressDialog dialog;
        Socket request = null;
        ObjectInputStream in = null;
        ObjectOutputStream out = null;

        Fetcher(Poi poi, int k, int uid)
        {
            this.k = k;
            this.uid = uid;
            this.poi = poi;
        }

        @Override 
        protected Poi[] doInBackground(Void... v)
        {
            Poi[] result = null;

            try
            {
                request = new Socket(IP_ADDRESS, PORT);
                out = new ObjectOutputStream(request.getOutputStream());
                in = new ObjectInputStream(request.getInputStream());

                result = fetch(); // <-- Gets null.
            }
            catch(IOException ioExc)
            {
                ioExc.printStackTrace();
            }
            finally
            {
                try
                {
                    out.close();
                    in.close();
                    request.close();
                }
                catch(IOException ioExc)
                {
                    ioExc.printStackTrace();
                }
            }

            return result;
        }

        Poi[] fetch() throws IOException
        {
            Poi[] recs = null;

            try
            {
                out.writeInt(uid);
                out.writeUnshared(LOCATION);
                out.writeInt(k);
                out.flush();

                recs = (Poi[]) in.readUnshared(); // <-- This is where the exception is thrown, readUnshared returns null.
            }
            catch(ClassNotFoundException cnfExc)
            {
                cnfExc.printStackTrace();
            }

            return recs; // <-- Returns null.
        }

    private static final Poi LOCATION = // The location sent to the Server...;
}

这是Master类(服务器)。服务器读取包含位置数据(经度、纬度、图像 URL 等)的 JSON 文件。生成推荐后,它会下载图像并将所有信息发送回客户端。每次客户端连接到服务器时,Handler都会创建一个线程来为客户端服务。

public class Master
{
   private JSONObject pois;

   //  Constructor.
   public Master() { initialize(); }

   private void openServer()
   {
        // Do stuff[...]
        try
        {
            Thread t;
            //  Awaiting clients.
            System.out.println("Awaiting clients...\n");
            provider = new ServerSocket(C_PORT, BACKLOG);

            while(true)
            {
                connection = provider.accept();
                System.out.println("Client connected.");

                //  Creating request handler.
                t = new Handler(connection);

                t.start();
            }
           catch{Exception exc) {...}
           finally
           {
               try
               {
                   //  Closing server.
                   provider.close();
               }
               catch(IOException ioExc)
               {
                   ioExc.printStackTrace();
               }
           }
       }


       //  Returns the recommendations.
       private synchronized Poi[] getRecommendations(int u, int k, Poi poi)
       {
           // Produce recommendations...
       }

       // The Handler class handles the client requests.
       private class Handler extends Thread
       {
           private Poi poi;    //  POI received by the client.
           /*
            *  k: multitude of POIs to recommend.
            *  u: user id.
            */
            private int k, u;
            private Poi[] recs;     // Recommendations for the client.
            private Socket connection;

            public Handler(Socket connection) { this.connection = connection; }

            //  Extending Thread class.
            public void run()
            {
                ObjectInputStream in = null;
                ObjectOutputStream out = null;

               try
               {
                   //  Initializing streams.
                   in = new ObjectInputStream(connection.getInputStream());
                   out = new ObjectOutputStream(connection.getOutputStream());

                   u = in.readInt();       //  User id.
                   poi = (Poi) in.readUnshared();    //  POI.
                   k = in.readInt();       //  Number of POIs.

                   //  Producing recommendations.
                   recs = getRecommendations(u, k, poi);

                   //  Sending recommendations to client.
                   out.writeUnshared(recs); // <-- This does NOT send null.
                   out.flush();
              }
              catch(EOFException oefExc)
              {
                   System.out.println("Client disconnected.\n");
              }
              catch(IOException ioExc)
              {
                   ioExc.printStackTrace();
              }
              catch(ClassNotFoundException cnfExc)
              {
                   cnfExc.printStackTrace();
              }
              finally
              {
                   try
                   {
                        //  Closing streams and socket.
                        in.close();
                        out.close();
                        connection.close();
                   }
                   catch(IOException ioExc)
                   {
                        ioExc.printStackTrace();
              }
          }
      }

标签: javaandroid

解决方案


所以我想通了。我没有让服务器下载图像,然后将它们与所有其余数据一起发送给客户端,而是让客户端自己下载图像。我想我可以发送的数据量存在某种限制。


推荐阅读