使用UDP逐个发送文件

时间:2015-02-20 14:22:40

标签: java android udp

我会在服务器端发送一个分成N个部分的XML文件。

每个文件在开始时都包含以下信息:fileNumber和totalPart

例如,如果我有32个部分: - 第一个文件包含start:0(文件编号)和32(总部分) - 第二个文件包含start:1(文件编号)和32(总部分)...

使用for循环,我可以将所有部分同时发送给我的客户端。 但我的客户无法收到所有零件,我丢失了一些零件.. 我如何处理请求丢失的部分?

这是我的服务器端代码:

for (int i = 0; i < nbPart + 1; i++) {
  File f = null;
  BufferedReader br = null;
  String content = "";
  byte[] sendBuffer = null;
  try {
      f = new File("xml/file.part" + i);
      br = new BufferedReader(new FileReader(f));
      StringBuilder sbuilder = new StringBuilder();
      String line = br.readLine();
      while (line != null) {
          sbuilder.append(line);
          line = br.readLine();
          if (line != null) {
             sbuilder.append("\n");
          }
      }
      content = i + ";" + nbPart + "#tag#" + sbuilder.toString();
      int total = new Long(f.length()).intValue();
      sendBuffer = new byte[total];
      sendBuffer = content.getBytes();
      DatagramSocket sendSocket = new DatagramSocket();
      DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, source, PORT_SEND);
      sendSocket.send(sendPacket);
      sendSocket.close();
      Thread.sleep(timeToSend);
 } catch (Exception e) {
      e.printStackTrace();
 } finally {
      try {
          if (br != null)
             br.close();
      } catch (IOException ex) {
          ex.printStackTrace();
      }
 }

}

这是我的客户端代码:

while (run) {
   DatagramSocket receiveSocket = null;
   DatagramPacket receivePacket = null;
   data = "";
   byte[] receiveBuffer = new byte[9999];
   Arrays.fill(receiveBuffer, (byte) 0);
   try {
       receiveSocket = new DatagramSocket(PORT_RECEIVE);
       receivePacket = new DatagramPacket(receiveBuffer,receiveBuffer.length);
       receiveSocket.receive(receivePacket);
       receiveSocket.close();

       data = new String(receiveBuffer, receivePacket.getOffset(), receivePacket.getLength());

       String datas[] = data.split("#tag#");
       String dataParts[] = datas[0].split(";");
       int numPart = Integer.parseInt(dataParts[0]);
       totalPart = Integer.parseInt(dataParts[1]);

       if(partReceive.isEmpty()){
          for(int i=0;i<totalPart+1;i++){
              partReceive.add(Boolean.FALSE);
          }
       }

       File part = new File(filePath+"/file.part"+numPart);
       if(part.exists()) part.delete();
       writeToFile(part, datas[1]);
       partReceive.set(numPart, Boolean.TRUE);

       Log.wtf("Part"+numPart, partReceive.get(numPart).toString());

     } catch (Exception e) {
        e.printStackTrace();
     }
}

正如你所看到的,我的第一个想法是:在客户端,我创建一个包含boolean(False)的ArrayList partReceive,当我收到一个部分时,我将ArrayList的索引设置为&#34; True&#34 ;。但在我如何处理之后?

1 个答案:

答案 0 :(得分:0)

我想到了两种可能的方式:

  1. 使用TCP。它会自动确保按顺序接收所有数据包。
  2. 也许你故意要用UDP。我不太了解你的ArrayList partReceive的意义。循环将alawys将所有元素设置为false,因为totalPart在整个传输过程中是恒定的。在您的示例中,它将始终为32.我宁愿为每个数据包分配ID。 ID是唯一编号。例如,您可以使用numPart。收到数据包时,将其ID存储在列表中。整个传输完成后,检查仍然缺少哪些ID。最简单的方法是request each missing packet
  3. 像这样的东西

    ArrayList<Integer> receivedParts = new ArrayList<Integer>();
    
    // save id of received packet
    receivedParts.add(numPart);
    
    // ...
    // after transmission has finished
    
    // Keep in mind that packets do not necessarily need to arrive in the same order like you've sent them when using UDP.
    ArrayList<Integer> missingIDs = getMissingIDs(receivedParts);
    
    for(Integer currentID : missingIDs) {
    
        // request missing packets
        requestMissingPacket(currentID);
    }
    

    有多种方法可以检查传输是否已完成:

    • 收到所有数据包后,传输。只需检查receiveParts列表的大小。
    • 使用timeout。例如,如果您在x seonds期间没有收到任何数据包,请考虑完成传输。然后检查丢失的数据包。