0

I would send a XML file splitted into N parts in my server side.

Each files contains at start this informations : fileNumber and totalPart

For example if I have 32 parts : - the first file contain at start : 0 (file number) and 32 (total parts) - the second file contain at start : 1 (file number) and 32 (total parts)...

With a for loop, I can send all the parts in the same time to my client. But my client can't receive all the parts, I lost some parts.. How I can process for requested the missing parts ?

This is my server side code :

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

}

And this is my client side code :

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

As you can see, my first idea is : In client side, I create an ArrayList partReceive who contains boolean (False), when I receive a part, I set the index of the ArrayList to "True". But after How I can process ?

Franck
  • 19
  • 1
  • 9

1 Answers1

0

Two possibles ways that come to my mind:

  1. Use TCP. It automatically ensures that all packets are received in order.
  2. Maybe you deliberately want you use UDP. I don't quite understand the sense of your ArrayList partReceive. The loop will alawys set all elements false, as totalPart is constant throughout a transfer. In your example it will always be 32. I would rather assign an ID to each packet. An ID is a unique number. You could use numPart for example. When receiving a packet, store its ID in a list. After the entire transmission finished, check what ids are still missing. The easiest approach then would be to request each missing packet.

Something like that

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

There are different ways to check whether the tranmission has finished:

  • After having received all packets, the transmission. Just check the size of your receiveParts list.
  • Use a timeout. For example if you don't receive any packet during x seonds, consider the tranmission finished. Then check what packets are missing.
null
  • 1,369
  • 2
  • 18
  • 38
  • I should use UDP I haven't choice, How I can assign an ID to each packet ? And how I can sure that the transmission is finished ? I have a while loop.. The sense of my partReceive ArrayList is for check if I have received the second packet for example, I check partReceive.get(1), if it return false, I haven't received the second packet, but if it return true, I have received this packet... – Franck Feb 20 '15 at 15:00
  • See my modified answer. Are there any remaining questions? – null Feb 20 '15 at 15:16
  • Can you give me an example for set a timeout for my code ? – Franck Feb 20 '15 at 15:28
  • Check this out http://stackoverflow.com/questions/19456313/simple-timeout-in-java – null Feb 20 '15 at 15:33
  • Thanks but in my case how I can verify if I don't receive any packet during x seconds ? – Franck Feb 20 '15 at 15:39
  • Hi, you could use a variable of type boolean. It becomes "true" as soon as all packets are received. If it is still negative after the timeout, you know that not all packets were successfully delivered. But actually this is another question. Please pose a new question and mark this one solved as far as the inital question was answered well. – null Feb 20 '15 at 16:59