我一直在尝试解决这个问题,我在stackoverflow(和其他网站)上阅读了其他线程,但无法找到答案。
基本上,我正在开发一个通过套接字发送apk文件的应用程序。在我开始发送文件之前,我还发送一个包含应用程序名称和相应apk文件大小的字符串。
当我创建套接字时(在开始时),我还发送两条消息,一条从客户端发送到服务器,说出它的昵称,一条从服务器发送到客户端,只是打招呼。这些消息发送正常。
问题在于我尝试读取appName和fileSize。
编辑:刚刚注意到错误格式异常后显示的字符不是来自错误。它会根据我尝试发送的应用程序而变化。这是我的代码。
这是内部类clientHandler(Runnable)的run方法,我在客户端创建流对象。
public void run() {
System.out.println("ServerComm clientHandler - inside the thread run ..");
try {
this.in=new ObjectInputStream(socket.getInputStream());//criar os streams para cada um dos clientes
this.out=new ObjectOutputStream(socket.getOutputStream());
try{
System.out.println("SErverComm clientHandler - going to read the nickname.");
String message = (String)this.in.readObject();
String[] tmp=message.split(";:-");
this.nickname=tmp[1];
System.out.println("ServerComm clientHandler - the nickname of this person is : "+nickname);
this.out.writeObject("Hello i am the server");
System.out.println("serverComm clientHandler - just sent my message of hello from the server");
handshakeDone=true;
System.out.println("serverComm ClientHandler - the handshake is done ! ");
connectedClients.put(nickname,this);
ReceiveThread rec = new ReceiveThread(this);
new Thread(rec){}.start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
然后我启动接收线程,它也是一个内部,RUnnable类代码是:
private ClientHandler clientHandler;
public ReceiveThread(ClientHandler clientHandler) {
this.clientHandler = clientHandler;
}
@Override
public void run() {
try {
ObjectInputStream in = clientHandler.getIn();
while(!serverSocket.isClosed()){
try {
System.out.println("Highway server comm receive thread - INSIDE THE WHILE CICLE, before the in.readObject");
if(in==null){
System.out.println("serverComm - receiveThread the in object is null I am null");
}
if(handshakeDone){
System.out.println("The handshake was already done before, so lets start receiving !");
List<HighwayGridViewAppItem> listOfReceivedFiles=new ArrayList<HighwayGridViewAppItem>();
System.out.println("ServerComm receive thread - i am going to try to receive the filesize and name ! ");
String fileSizeAsString=(String)in.readObject();
System.out.println("Received this initial message with the size: " + fileSizeAsString);
String[] valor=fileSizeAsString.split(":");
String receivedApkName=valor[0]; //duplicated line pq acho que o nome da app n devia sofrer trim, nao vale a pena.
long fileSize=Long.parseLong(valor[1].trim());
System.out.println(" ServerComm receive thread : FileSize is at : "+fileSize + " o nome da app e : "+ receivedApkName);
File apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + ".apk");
int i=1;
while(apkReceived.exists()){
apkReceived=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/"+receivedApkName + "("+i+")"+".apk");
i++;
}
i=1;
byte[] buffer = new byte [8192];
FileOutputStream fos=new FileOutputStream(apkReceived);
int count=0;
int total=0;//so apra ir vendo quanto recebi.
while(total<=fileSize && (count = in.read(buffer)) != -1){
fos.write(buffer,0,count);
total+=count;
System.out.println("Server Comm receive thread - already received this ammount : "+total);
if(total==fileSize){
System.out.println("Reached the end of the file !");
total++;
System.out.println("Receive Thread ServerComm o canonical Path que ta e : " + apkReceived.getCanonicalPath());
HighwayGridViewAppItem aux=new HighwayGridViewAppItem(null, receivedApkName, apkReceived.getCanonicalPath());
listOfReceivedFiles.add(aux);
}
}
System.out.println("Already received everything ! ");
listOfApps=listOfReceivedFiles;
System.out.println("ServerComm : O size da lista de apps que recebi e que agora mudei para que possa reenviar pos outros ta a : "+listOfApps.size());
String clientName=clientHandler.getNickname();
SendThread sendThread = new
new Thread(sendThread){
}.start();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
**堆栈**是:
08-26 10:38:40.082 4704-5771/cm.aptoide.lite.debug W/System.err: java.io.StreamCorruptedException
08-26 10:38:40.082 4704-6297/cm.aptoide.lite.debug W/System.err: java.io.StreamCorruptedException: Wrong format: e
08-26 10:38:40.110 4704-5771/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2109)
08-26 10:38:40.110 4704-5771/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.<init>(ObjectInputStream.java:372)
08-26 10:38:40.110 4704-5771/cm.aptoide.lite.debug W/System.err: at cm.aptoide.lite.HighwayServerComm$ClientHandler.run(HighwayServerComm.java:203)
08-26 10:38:40.110 4704-5771/cm.aptoide.lite.debug W/System.err: at cm.aptoide.lite.HighwayServerComm$ConnectionHandler.run(HighwayServerComm.java:165)
08-26 10:38:40.110 4704-5771/cm.aptoide.lite.debug W/System.err: at java.lang.Thread.run(Thread.java:856)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.corruptStream(ObjectInputStream.java:701)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:814)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at cm.aptoide.lite.HighwayServerComm$ReceiveThread.run(HighwayServerComm.java:395)
08-26 10:38:40.111 4704-6297/cm.aptoide.lite.debug W/System.err: at java.lang.Thread.run(Thread.java:856)
第395行是:
String fileSizeAsString=(String)in.readObject();
这是我尝试读取appName和fileSize(String)的地方。
如果你们想要我也可以发布clientSide,但我知道它工作正常,它会发送文件。 另外我不知道为什么在堆栈中它也指向clientHandler线程的run方法,它不应该。在clientHandler之前还有另一个接受客户端套接字的线程,然后启动clientHandler,将套接字作为参数。
这是我的客户代码:
我有一个连接处理程序嵌套类,只是为了处理流对象和套接字的创建。
public class ConnectionHandler implements Runnable{
@Override
public void run() {
try {
clientSocket = new Socket (serverIP,porto);
out = new ObjectOutputStream(clientSocket.getOutputStream());
in= new ObjectInputStream(clientSocket.getInputStream());
System.out.println("client comm receive thread - doing the Initial handshake");
System.out.println("CLientComm connection handler : sending my initial message hello - my nickname is : "+nickname);
out.writeObject("Nickname:-:"+nickname);
System.out.println("ClientComm : Just sent my initial message.");
try {
String message = (String) in.readObject();
System.out.println("ClientComm :_ jist read : " + message );
System.out.println("Client Comm receive thread - receive the handshake message from the server. Handshake is done.");
handshakeDone=true;
ReceiveThread receiveThread = new ReceiveThread();
new Thread(receiveThread).start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里我开始接收线程,它将等待接收消息,但在布局中我有一个发送按钮,它将发送一个选择的apk(它将使用ACTION =&#34再次运行此服务;发送&#34;然后onStartCommand如果动作发送,则运行线程SendThread。
以下是该sendTread的代码:
public class SendThread implements Runnable{
@Override
public void run() {
try {
//percorrer a lista de apps a enviar
File apkToSend;
long apkToSendSize;
for(int i=0;i<listOfApps.size();i++){
HighwayGridViewAppItem tmp=listOfApps.get(i);
filePath=tmp.getFilePath();
appName=tmp.getAppName();
apkToSend=new File(filePath);
if(apkToSend.exists()){
apkToSendSize=apkToSend.length();
String apkSize=Long.toString(apkToSendSize);
System.out.println(appName +": " +apkSize);
out.writeObject(""+appName +": "+ apkSize);//appName to send to have the name of the file
System.out.println("ClientComm send thread : going to send this "+appName+": "+apkSize);
byte[] buffer = new byte [8192];
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(apkToSend));
int count;
int total=0; // so para testes - para saber quanto enviei.
while((count=bis.read(buffer))!=-1){
System.out.println("buffer values : " + buffer[0]);
out.write(buffer,0,count);
total+=count;
out.reset();
System.out.println("Client Comm send thread - already sent this ammount : "+total);
}
out.flush();
bis.close();
try {
System.out.println("Just sent the app : "+appName);
Thread.sleep(1000);//just to separate each file, to make sure there are no problems with the other side receiving and this one sending
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println("There was a problem with the file, the path was incorrect, probably.");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在接收方(它给出错误的地方)读取的消息是
out.writeObject(""+appName +": "+ apkSize);//appName to send to have the name of the file
请注意,在处理连接的线程(clientHandler和ConnectionHandler)之前,我正在成功发送和交易我想要的数据。问题只出现在那里的线程上。