-1

我的发件人和服务器 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 指出的那样,您还需要考虑如果数据包没有到达、两次到达或乱序时会发生什么,但解决您当前问题的方法是每个数据包都有一个新的 OOS。

于 2012-06-09T21:26:47.080 回答
0

嗯,你完全忘了实现一个协议!您忘记了传输步调、重复数据报检测、校验和、数据报重新排序、重新传输、确认、慢启动、滑动窗口以及几乎所有其他事情!您可能并不绝对需要所有这些东西,但您需要其中的大部分,或者您需要以其他方式完成这些基本功能。

您已经完成了大约 1% 的使用 UDP 发送数据的工作。在你完成工作之前它不会起作用。

如果您希望通过 UDP 进行最少的文件传输,那么 TFTP 就是您要研究的内容。以下是如何通过 UDP 进行文件传输的描述:

发起主机 A 在众所周知的端口号 69 上向主机 S 发送一个 RRQ(读请求)或 WRQ(写请求)数据包,其中包含文件名和传输模式。

S 用 ACK(确认)数据包回复 WRQ,并直接用 DATA 数据包回复 RRQ。数据包是从一个新分配的临时端口发送的,所有未来发送到主机 S 的数据包都应该发送到这个端口。

源主机向目标主机发送编号的 DATA 数据包,除了最后一个之外,所有数据包都包含完整大小的数据块(512 字节)。目标主机对所有 DATA 数据包使用编号的 ACK 数据包进行回复。

最终的 DATA 包必须包含小于一个完整大小的数据块,以表明它是最后一个。如果传输文件的大小是块大小的精确倍数,则源发送包含 0 字节数据的最终 DATA 包。

接收器使用相关编号的 ACK 响应每个 DATA。发送者用下一个块的 DATA 响应块的第一个接收到的 ACK。

如果最终没有收到 ACK,则重传计时器重新发送 DATA 包。

普通文件传输协议- 维基百科

这避免了通过一次只保持一个数据块“在飞行中”来进行传输起搏、慢启动、窗口或数据报重新排序的需要。这使得它非常慢,但也很简单。如上所述,每次往返时间最多可以交换 512 个字节。

于 2012-06-08T08:39:07.070 回答