所以我必须使用Android客户端实现推荐系统。系统的工作方式如下:用户将其位置和所需建议的数量发送到服务器。然后服务器产生推荐并发回推荐的Pois(兴趣点)。
这是我的问题。当客户端从服务器读取Pois[]
数组(实际建议)时,将引发StreamCorruptedException
。奇怪的是,当我在自己的计算机上运行应用程序时,这种情况永远不会发生。它只发生在我大学的计算机上运行时。它不会发生总是。这可能是我运行它的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();
}
}
}
答案 0 :(得分:0)
所以我明白了。我没有让服务器下载图像,然后将所有其他数据发送到客户端,而是让客户端自己下载图像。我想我可以发送的数据量存在某种限制。