2015-10-01 129 views
0

您好,我正在尝试使用UDP将1 KB的数据包从客户端发送到服务器。我可以收到所有的数据包,但问题是while循环没有退出,所以我使用套接字超时来实现这一点。因为这不适合动态环境,我想替换一些明智的东西。下面是我的服务器和客户端代码,客户端从while循环跟随服务器端。我只是想实现RDT 1.0,其中数据包分为1kb并通过UDP套接字发送,以在另一端接收。但是,在接收所有1kb数据包时,我尝试了很多事情来退出while循环,最后在接收端设置套接​​字超时。我还声明'我'(我知道我的文件大小)脱离循环,以便在超时之前执行其余的编码。是否有一种方法可以更改我的while循环,以便它适合所有环境(发送N个数据包)。在UDP中接收数据包 - Java

//Client side 
    class Client 
{ 
    public static DatagramSocket sock =null; 
    public static FileInputStream in=null; 
    public static DatagramPacket[] sendpacket=new DatagramPacket[1024]; 
public static void main(String[] args) throws Exception 
{ 
    byte[] array = new byte[1024]; 
    DatagramSocket sock = new DatagramSocket(); 
    InetAddress ip= InetAddress.getByName("localhost"); 
    Scanner scanner = new Scanner(System.in); 
    System.out.println("Enter a file name: "); 
    System.out.flush(); 
    String filename = scanner.nextLine(); 
    File file = new File(filename); 
    in=new FileInputStream(file); 
    int length =0,checksum=0,h=1; 
    while((length = in.read(array))!=-1) 
    { 
     sendpacket[h]=new DatagramPacket(array,array.length,ip,1234); 
     sock.send(sendpacket[h]); 
     checksum+=length; 
     System.out.println("Sent packet "+h); 
     System.out.println(length); 
     System.out.println(checksum); 
     h++; 
     } 
     in.close(); 

} 
} 





//Server side 
public class server 
{ 
    public static DatagramPacket[] recvpacket=new DatagramPacket[100]; 
    public static DatagramSocket sock=null; 
    public static FileOutputStream fos=null; 
    public static BufferedOutputStream bos=null; 
    public static void main(String args[]) 
    { 

    try 
     { 
     try 
     { 
     sock=new DatagramSocket(1234);//opening a socket 
    } 
    catch(IOException ex) 
    { 
    System.out.println(ex); 
    } 
    sock.setSoTimeout(30000); 
    boolean socketalive=true; 
    byte[] array=new byte[1024]; 
    int i=1,checksum=0; 
    System.out.println("server is ready to receive packets"); 
    while(recvpacket!=null)//I need change in this loop 
    { 
    recvpacket[i]=new DatagramPacket(array,array.length); 
    sock.receive(recvpacket[i]); 
    System.out.println("server received packet "+i); 
    int length=array.length; 
    checksum+=length; 
    System.out.println(length);//here i get the size of the buffer so //checksum is wrong 
    System.out.println(checksum); 
    fos=new FileOutputStream(new File("profile1.docx"),true); 
    fos.write(array); 
    for(int j=0; j<1024; j++) 
    { 
     array[j]=0; 
    } 
    i++; 
    }//while 
    System.out.println("server received packet "+i); 
    }//try 
    catch(IOException e) 
    { 
    System.out.println(e); 
    } 
    }//main 
    }//class 

回答

1

有几个问题可能会遇到这个问题。 UDP不像TCP那样可靠,因此数据包可能会丢失或者更糟,可能会出现乱序。在将数据写入文件之前,您需要将数据存储在本地缓冲区中,或者将数据写入文件中的适当位置(可能会留下一个空间)。

理想情况下,UDP监听循环应该在其自己的线程中,以便其他代码可以运行。如果您想要通过UDP实现一种FTP,那么您需要在开始时发送包含传输信息的数据包,例如大小,数据包数,校验和。然后,对于每个数据包,还需要为单个数据包包含一个序列号和一个校验和。在最后(或沿途),服务器需要回复客户端请求丢失/损坏的数据包。我建议最后发送一个“传输完成”数据包。

如果所有的数据包都已收到并且没有损坏,那么您可以终止循环!

你应该能够找到一些能够为你处理所有这些事情的存在,而不是从头开始编写它,但是如果你必须自己编写它,那么你必须复制TCP的开销。

+0

这是否意味着我不需要实现上述提到的事情,如序列号,校验和,ack(关于丢失重传包),如果我通过TCP在应用层发送/接收? –

+0

没错 - TCP处理所有这些事情。你不会使用它的原因是,如果你担心传输的延迟延迟,比如在线动作游戏。 – kbickar