1

問題は、 java.io.StreamCorruptedException: invalid type code: 9E 毎回コードが異なることです。

私が持っているのはクライアントサーバーアプリケーションであり、クライアントがアップロード状態にあり、サーバーがダウンロード状態にあるときに問題が発生します。

ユーザーが UI からボタンを押すと、選択したすべてのファイルが 1 つずつサーバーに転送されます。

ボタンのコードは次のとおりです。

try {
    _client.setProtocolFiles(_uploadTree.getFiles());
if(_uploadTree.getFiles().getFiles().size() > 0) {
    _client.write("iwanttoupload");
} else {
    CustomDialog.showInfoDialog("Πρέπει να επιλέξετε αρχεία", "Προσοχή");
}
} catch (Exception e) {
    e.printStackTrace();
}

クライアントのアップロード状態は次のとおりです。

@Override
public void interact(Object theInput) throws Exception {
    if(theInput.equals("uploadedsuccessfully")) {
        System.out.println("uploadedsuccessfully");
        _client.setState(new TranferState(_client));
    } else if(theInput.equals("letsgo") || theInput.equals("sendmemore")) {
        if(_fileToBeSent < _client.getProtocolFiles().getFiles().size())
            sendFiles(theInput);
        else
            _client.write("iuploadedall");
        _fileToBeSent++;
    } else if(theInput.equals("idontunderstandyou")) {
        _client.setState(new TranferState(_client));
    }
}

private void sendFiles(Object theInput) throws Exception {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(new File(_client.getProtocolFiles().getFiles().get(_fileToBeSent).getPath()));
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        _client.getProtocolFiles().getFiles().get(_fileToBeSent).setFile(buffer);
        try {
            _client.write(_client.getProtocolFiles().getFiles().get(_fileToBeSent));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } catch(IOException ex) {
        System.out.println(ex.getMessage());
        _fileToBeSent++;
        interact(theInput);
    }
}

これはサーバーのダウンロード状態です:

@Override
public String reply(Object theInput) {
    String outPut = "";
    if(theInput.equals("iuploadedall")) {
        outPut = "uploadedsuccessfully";
        _connection.setConnectionState(new TranferState(_connection));
    } else if (theInput.equals("startedupload")) {
        outPut = "letsgo";
    } else if(theInput instanceof ProtocolFile) {
        try {
            System.out.println(theInput.toString());
            ProtocolFile file = (ProtocolFile)theInput;
            FileOutputStream fos = new FileOutputStream("C:\\" + file.getName());
            fos.write(file.getFile());
            fos.close();
            outPut = "sendmemore";

        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        outPut="idontunderstandyou";
        _connection.setConnectionState(new TranferState(_connection));
    }
    return outPut;

}

これはすべて、次の順序でうまく機能します。

  1. ユーザーが「iwanttoupload」をクリックして送信
  2. サーバーはOKを送信します。---- クライアントとサーバーは上記の状態になりました。
  3. クライアントは「startupload」を送信します
  4. サーバーは「letsgo」を送信します
  5. クライアント送信 ProtocolFile (シリアル化)
  6. サーバーは、クライアントから「iuploadedall」を取得するまで「sendmemore」を送信します

これは、ユーザーがボタンを 1 回押して、アップロードが待機するのを待ってからもう一度押すとうまく機能します。アップロードが完了する前にユーザーがそれを押すと、この例外が発生します。

簡単な修正の 1 つは、クライアントの状態が転送状態の場合にユーザーがボタンを押したときに確認することです。それ以外の場合はアクションを実行しませんが、ソケットの問題を修正するか、なぜこれが起こっているのかを理解したいと考えています。シリアル化されたオブジェクトを読み込もうとすると、新しいアップロードがデータを送信し、混乱があると思います。私の実装された状態は、メッセージに従って通信を回避しますが、メッセージは送信され、問題があります。

クライアント書き込みコード:

public void write(Object credentials) throws Exception {
if (credentials != null && _socket !=null && !_socket.isClosed()) {
        _oos.writeObject(credentials);
} else {
     connect();
     _oos.writeObject(_credentials);
    _oos.flush();
    _oos.writeObject(credentials);
}
_oos.flush();
}

サーバー読み取りコード:

while ((input = ois.readObject()) != null) {
    if (_connectionState.getClass().equals(ClosedState.class)) {
    break;
}
oos.writeObject(Protocol.processInput(input, _connectionState));
oos.flush();
}

例外はここにあります:

while ((input = ois.readObject()) != null)
4

1 に答える 1

1

問題は、ボタンコードでクライアントにすぐに書き込むことだと思います:

if(_uploadTree.getFiles().getFiles().size() > 0) {
    _client.write("iwanttoupload");
}

バックグラウンド スレッドでクライアント通信を処理する一般的なパターンに従っている場合は、そのスレッドからのみストリームに書き込む必要があります。ボタンは、機会があればそのスレッドによって処理される通知をエンキューする必要があります。

このエラーが表示されるのは、バックグラウンド スレッドによって書き込まれるオブジェクトの途中に「iwanttoupload」が挿入され、ストリームが破損するためです。

于 2013-07-08T20:33:41.693 に答える