Java 发送方和服务器UDP问题

Java 发送方和服务器UDP问题,java,udp,client,server-side,Java,Udp,Client,Server Side,我的发送方和服务器UDP有问题。SenderUDP发送一个对象,而ServerUDP必须接收该对象。对于第一个对象,一切正常,但当我尝试发送另一个对象时,服务器抛出一个StreamCorruptedException。 以下是客户端代码: public class SenderUDP implements Runnable { private java.net.DatagramSocket clientsocket; private ObjectOutputStream out; private

我的发送方和服务器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);
        }
    }
}
}

以下是服务器端代码:

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));


谢谢

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

您已经完成了大约1%的使用UDP发送数据的工作。直到你完成这项工作,它才会起作用

如果您希望通过UDP进行最小的文件传输,那么TFTP就是您想要研究的内容。下面描述了通过UDP进行文件传输的方式:

发起主机A在众所周知的端口号69处向主机S发送RRQ(读取请求)或WRQ(写入请求)分组,其中包含文件名和传输模式

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

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

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

接收器用相关编号的ACK响应每个数据。发送方用下一个块的数据响应一个块的第一个接收到的ACK

如果最终没有接收到ACK,则重传定时器重新发送数据分组

-维基百科


这避免了一次只保留一个数据块“飞行”,从而进行传输速度调整、慢启动、窗口或数据报重新排序的需要。这使得它非常慢,但也非常简单。如上所述,每次往返时间最多只能交换512字节。

每次在另一端有新的ObjectOutputStream时,都需要使用新的ObjectInputStream,而不是在其他时间。在这种情况下,您使用的是UDP,其中数据报是独立的,因此每个数据包都需要一个新的OIS,所以每个数据包也需要一个新的OOS


正如David Schwartz指出的,Y++也需要考虑如果数据包不到达,或者到达两次或无序,会发生什么,但是解决你的问题是一个新的OOS包。

为什么你不使用TCP来传输对象?嗨!首先谢谢你的回答!我忘了说我用UDP只发送了一段。客户端的main检查文件的大小,如果小于60k,则以UDP发送。否则它会发送TCP。所以我认为我不需要校验和等,因为我总是只发送一个数据包UDP。你把数据包和数据报混淆了。你不能发送一个60K的数据包(除非这是一个全是GigE和巨型帧的私有内部网)。携带这么大的数据报大约需要40个数据包。即使数据报的一个数据包丢失,数据报也会丢失。例如,如果数据包丢失率为.5%,则数据报丢失率将为87%!也就是说,您的数据报将通过八次中的一次。所以,至少,你需要确认和重新传输。好吧,也许我表达得很糟糕。在我的应用程序中,数据包是一个包含2个字符串、1个int、1个File的对象。我需要发送这个对象。我检查文件的大小。如果这个大小合适,那么您需要编写一个协议。看来你没有那样做。如果您将其作为一个大数据报发送,则需要进行重传和确认。如果没有,则需要执行重复数据报检测、传输速度调整等。(您可能需要阅读TCP规范。TCP所做的一切都是您需要的,如果您想使用UDP,您必须这样做。)好的,明白了!谢谢你的回答!有一些实现协议的教程吗?我真的不知道!