StreamCorruptedException格式错误

时间:2016-08-26 10:07:55

标签: java android multithreading sockets io

我一直在尝试解决这个问题,我在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)之前,我正在成功发送和交易我想要的数据。问题只出现在那里的线程上。

0 个答案:

没有答案