-1

Sender と Server UDP に問題があります。はSenderUDPオブジェクトを送信し、ServerUDPはそれを受信する必要があります。最初のオブジェクトはすべて正常に動作しますが、別のオブジェクトを送信しようとすると、サーバーがStreamCorruptedException. クライアント側のコードは次のとおりです。

public class SenderUDP implements Runnable {
private java.net.DatagramSocket clientsocket;
private ObjectOutputStream out;
private int port;
private InetAddress ip;
private Packet objToSend;
private ByteArrayOutputStream baos;


public SenderUDP(String ip, int port, Packet p) throws UnknownHostException{
    this.ip =InetAddress.getByName(ip);
    this.port = port;
    this.objToSend = p;
    this.out = null;
    this.clientsocket = null;
}

@Override
public void run(){
    try{
        clientsocket = new DatagramSocket ();
        System.out.println("Inside senderUDP");
        byte[] sendData;                    
        baos = new ByteArrayOutputStream(1024);
        out = new ObjectOutputStream(baos);
        out.writeObject(objToSend);
        sendData = baos.toByteArray();           
        DatagramPacket sendpacket = new DatagramPacket(sendData,sendData.length,ip,port);            
        clientsocket.send(sendpacket);                 
        System.out.println("Sended packet with UDP");
        out.flush();
        if(this.objToSend.getOP() == 1){
            byte[] buf = new byte[1024];                
            int read;
            ByteArrayOutputStream bas = new ByteArrayOutputStream((int)this.objToSend.getFile().length());                
            FileInputStream fis = new FileInputStream(objToSend.getFile());
            while((read = fis.read(buf)) != -1){
                bas.write(buf, 0, read);
            }
            DatagramPacket sendfile = new DatagramPacket(bas.toByteArray(), bas.toByteArray().length, ip, port);
            clientsocket.send(sendfile);
        }           
        out.close();             
    }
    catch(UnknownHostException uhe) {
        System.err.println(uhe.getMessage());
    }
    catch(IOException ioe) {
        System.err.println(ioe.getMessage());
    }
}

}

サーバー側のコードは次のとおりです。

class ServerUDP implements Runnable {
private DatagramSocket socket;
private int port;
private Controller controller;
private byte[] buffer;
private DatagramPacket packet;
private Packet p;
private ObjectInputStream ois;

public ServerUDP(int port, Controller controller){
    this.socket = null;
    this.port = port;
    this.controller = controller;
}

@Override
public void run() {
    try {
            socket = new DatagramSocket(port);
        } catch (SocketException ex) {
            Logger.getLogger(ServerUDP.class.getName()).log(Level.SEVERE, null, ex);
        }
    while(true){               
        buffer = new byte[1000000];
        packet = new DatagramPacket(buffer,buffer.length);
        System.out.println("Ascolto UDP!");
        try {                
            socket.receive(packet);
            System.out.println(packet);
            System.out.println("1");
        } catch (IOException ex) {
            Logger.getLogger(ServerUDP.class.getName()).log(Level.SEVERE, null, ex);
        }
        System.out.println("Packet UDP Received!");
        try {
            ois = new ObjectInputStream(new ByteArrayInputStream(buffer));
        } catch (IOException ex) {
            Logger.getLogger(ServerUDP.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            p = (Packet) ois.readObject();
            System.out.println("Pacchetto/Evento arrivato con UDP!");
            System.out.println(p);
        } catch (IOException | ClassNotFoundException ex) {
            Logger.getLogger(ServerUDP.class.getName()).log(Level.SEVERE, null, ex);
        }
        if(p.getOP() == 1){
            Thread t = new Thread(new FilesManager(socket,p,false, controller));
            t.start();
        }
        controller.enqueue(p);
        try {
            ois.close();
        } catch (IOException ex) {
            Logger.getLogger(ServerUDP.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

}

が投げStreamCorruptedExceptionられる

ois = new ObjectInputStream(new ByteArrayInputStream(buffer));

p = (Packet) ois.readObject();

ありがとう!

4

2 に答える 2

1

反対側に新しい ObjectOutputStream があるたびに新しい ObjectInputStream を使用する必要があり、それ以外の場合は必要ありません。この場合、データグラムが独立している UDP を使用しているため、パケットごとに新しい OIS が必要であり、パケットごとに新しい OOS も必要です。

David Schwartz が指摘しているように、+また+、パケットが到着しない場合、2 回到着する場合、または順不同の場合に何が起こるかを考慮する必要がありますが、差し迫った問題の解決策はパケットごとの新しい OOS です。

于 2012-06-09T21:26:47.080 に答える
0

うーん、プロトコルを実装するのを完全に忘れていました! 送信ペーシング、重複データグラムの検出、チェックサム、データグラムの並べ替え、再送信、確認応答、スロー スタート、スライディング ウィンドウ、その他ほとんどすべてを行うのを忘れていました。これらすべてが絶対に必要なわけではありませんが、ほとんどが必要であるか、これらの基本機能を別の方法で実行する必要があります。

UDP を使用してデータを送信する作業の約 1% を完了しました。仕事が終わらない限りうまくいきません。

UDP でのファイル転送を最小限に抑えたい場合は、TFTP を検討してください。UDP を介したファイル転送がどのように行われるかについては、次のとおりです。

開始ホスト A は、ファイル名と転送モードを含む RRQ (読み取り要求) または WRQ (書き込み要求) パケットを既知のポート番号 69 でホスト S に送信します。

S は ACK (確認) パケットで WRQ に応答し、直接 DATA パケットで RRQ に応答します。パケットは新たに割り当てられた一時ポートから送信され、ホスト S への今後のすべてのパケットはこのポートに送信される必要があります。

送信元ホストは番号付きの DATA パケットを宛先ホストに送信します。最後を除くすべてがフルサイズのデータ​​ ブロック (512 バイト) を含んでいます。宛先ホストは、すべての DATA パケットに対して番号付きの ACK パケットで応答します。

最後の DATA パケットには、それが最後であることを通知するために、フル サイズのデータ​​ ブロックよりも少ないサイズのデータ​​が含まれている必要があります。転送されたファイルのサイズがブロック サイズの正確な倍数である場合、ソースは 0 バイトのデータを含む最終的な DATA パケットを送信します。

受信者は、関連付けられた番号付き ACK で各データに応答します。送信者は、ブロックの最初に受信した ACK に次のブロックの DATA で応答します。

最終的に ACK が受信されない場合、再送信タイマーが DATA パケットを再送信します。

簡易ファイル転送プロトコル- ウィキペディア

これにより、一度に「飛行中」のデータ チャンクを 1 つだけ保持することで、送信ペーシング、スロー スタート、ウィンドウ、またはデータグラムの並べ替えを行う必要がなくなります。そのため、非常に遅くなりますが、非常に単純でもあります。上で説明したように、1 ラウンド トリップ時間あたり最大で 512 バイトを交換できます。

于 2012-06-08T08:39:07.070 に答える