java - 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();
}
}
}
解决方案
所以我想通了。我没有让服务器下载图像,然后将它们与所有其余数据一起发送给客户端,而是让客户端自己下载图像。我想我可以发送的数据量存在某种限制。
推荐阅读
- azure-devops - 如何在单个 CSV 文件中导入包含问题和史诗(父链接)的 Azure DevOps CSV 文件
- python - 如何使用 subprocces 库使用 python 打开新的 Powerpoint 文件?
- java - JAVA 中的 Oracle next_day 函数等效项
- r - 测试保存ggplots
- spring - 透明地批量存储
- c++ - constexpr 禁止使用超出范围的数组指针
- python - Azure Functions 如何在脚本完成之前返回 HttpResponse 或显示消息
- .net - NuGet 包:将 dll 和配置文件放在子目录下
- xslt - XSLT 将数字添加到子字符串
- python - 在 PyQT5 中使用信号和插槽时,有没有办法从不同的 python 文件调用函数?