2013-12-11 1 views
2

Моя проблема проста для объяснения. У меня есть многоадресный отправитель и многоадресный приемник. Я попытался отправить большой файл размером 8 МБ. Он должен быть разделен в 1024 байтовых пакетах + 4 байтовых заголовка. Отправка в порядке, но приемник отменяет прием в позиции 5000 иногда в 2000 или 3000. Я не знаю, почему он не получает все элементы.Java Multicast Sender + Receiver

ОТПРАВИТЕЛЬ:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.InetAddress; 
import java.net.InetSocketAddress; 
import java.net.MulticastSocket; 

public class Sender extends Thread{ 

protected static MulticastSocket socket = null; 
public int QuoteCount = 0; 
public int Time_Interval = 6000; 
public static FileInputStream in; 
final static int split_size = 1028 ; 

public static void main(String[] args) throws IOException{ 
    // args 0 => path 
    // args1=> ip multicast 
    // args2 => networkinterface ip 
    // args3 => port 
    // args4 => ttl 
    //socket = new MulticastSocket(444); 
    InetAddress ip_address_group = InetAddress.getByName(args[1]); 
    System.out.println("Wait 4 clients to connect..."); 
    File file=new File(args[0]); 

    InetSocketAddress address = new InetSocketAddress(args[1],Integer.parseInt(args[3])); 
    MulticastSocket socket = new MulticastSocket(new InetSocketAddress(args[2], Integer.parseInt(args[3]))); 
    socket.connect(address); 
    socket.setTimeToLive(Integer.parseInt(args[4])); 

    MD5 md5 = new MD5(); 
    try { 
     System.out.println("MD5 vom File: "+md5.getFileMD5(args[0])); 
    } catch (Exception e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
    } 

    // Filesize package 
    int filesize = (int)file.length(); 

    double anzpak=(filesize/1028); // anzahl pakete 
    double diagrammgrenze=(80/anzpak); // wieviele stricherl setzt ein paket 
    double strikecount=0; 
    System.out.println("DIAGR: "+diagrammgrenze +" Anzpak: "+anzpak); 

    byte[] firstpack=new byte[4]; 
    int2bytearr(filesize,firstpack); 
    DatagramPacket firsttosend=new DatagramPacket(firstpack,firstpack.length,ip_address_group, Integer.parseInt(args[3])); 
    socket.send(firsttosend); 

    // Rest of packages 
    in = new FileInputStream(file); 

    byte[] data = new byte[split_size]; 
    int numbytes = 0; 
    int seqnr = 0; 
    int sentbytes=0; 

    try { 
     while((numbytes = in.read(data)) != -1){ 
      // Generate 4 byte long seqnr: 
      seqnr++; 
      strikecount+=diagrammgrenze; 
      if(strikecount>=1){ 
       for(int i=0;i<(int)strikecount;i++){ 
        System.out.print("|"); 
        strikecount--; 
       } 
      } 

      byte[] dataseq = new byte[4]; 
      int2bytearr(seqnr,dataseq); 
      sentbytes+=numbytes; 

      // DATA PLUS SEQNR Generation 
      byte[] seqplusdata = new byte[dataseq.length + data.length]; 
      System.arraycopy(dataseq, 0, seqplusdata, 0, dataseq.length); 
      System.arraycopy(data, 0, seqplusdata, dataseq.length, data.length); 

      // Data Plus Seqnr Sending 
      DatagramPacket tosend=new DatagramPacket(seqplusdata,seqplusdata.length); 
      socket.send(tosend); 
     } 

    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    System.out.println("\nTosend filesize: "+filesize); 
    System.out.println("Sent bytes: "+sentbytes); 
    //in.close(); 
    socket.close(); 
} 

public static void int2bytearr(int number,byte[] data){ 
    for (int i = 0; i < 4; ++i) { 
     int shift = i << 3; // i * 8 
     data[3-i] = (byte)((number & (0xff << shift)) >>> shift); 
    } 
} 

} 

ПРИЕМНИК:

import java.io.IOException; 
import java.net.MulticastSocket; 
import java.net.DatagramPacket; 
import java.net.InetAddress; 

public class Empfaenger extends Thread{ 

public static void main(String[] args) throws IOException{ 
    Empfaenger empfaenger = new Empfaenger(); 
    empfaenger.start(); 
} 

@SuppressWarnings("resource") 
public void run(){ 
    try{ 

     //Create socket 
     MulticastSocket socket = new MulticastSocket(12345); 

     //Connect to server (must be multicast) 
     InetAddress IP_Adress = InetAddress.getByName("228.5.6.7"); 
     socket.joinGroup(IP_Adress); 

     DatagramPacket packet; 
     int pcount=0; 

     // firstpack for getting filesize package 
     byte[] firstpack = new byte[4]; 
     DatagramPacket firstpacket=new DatagramPacket(firstpack,firstpack.length); 
     socket.receive(firstpacket); 
     int filesize=makeintfrombyte(firstpack); 
     System.out.println("Empfaenger filesize: " + filesize); 

     double anzpak=(filesize/1028); // anzahl pakete 
     double diagrammgrenze=(80/anzpak); // wieviele stricherl setzt ein paket 
     double strikecount=0; 

     for(int i=0;i<anzpak;i++){ 
      System.out.println(pcount + "< "+anzpak); 

      strikecount+=diagrammgrenze; 
      if(strikecount>=1){ 
       while(strikecount>=1){ 
        System.out.print("|"); 
        strikecount--; 
       } 
      } 

      byte[] buf = new byte[1028]; 
      packet = new DatagramPacket(buf, buf.length); 
      socket.receive(packet); 
      pcount++; 
      //System.out.println("SeqNr. in Bytes: "+buf[0]+"|"+buf[1]+"|" +buf[2]+"|" +buf[3]+"|" + pcount); 
     } 
     //socket.leaveGroup(IP_Adress); 
     //socket.close(); 

    }catch (IOException X) {System.out.println(X);} 
} 

public int makeintfrombyte(byte[] b){ 
    return b[0] << 24 | (b[1] & 0xff) << 16 | (b[2] & 0xff) << 8 | (b[3] & 0xff); 
} 

} 

Вот образец Ouput от приемников и одного отправителя] http://i.stack.imgur.com/UblCa.jpg

EDIT: Если мы позволим спать отправителе для (long) 1.0 работает, но не означает, что отправитель должен спать :(

ответ

3

Дейтаграммы не имеют гарантированной доставки, поэтому это не идеальный протокол для передачи файлов. Вместо этого вы можете рассмотреть надежный протокол многоадресной рассылки.

И, наконец, если ваша скорость передачи выше, чем ваша скорость приема, вы в конечном итоге отбросите пакеты. Фактически, даже если ставки очень схожи, любого временного замедления на принимающей стороне (например, планировщика, сборщика мусора, ...) может быть достаточно, чтобы начать падение. Увеличение размера базового сетевого буфера с вызовом setReceiveBufferSize даст вам некоторый запас и значительно улучшит поведение. Значение по умолчанию обычно составляет 128 Кбайт, по крайней мере, в системах UX; попробуйте установить его на пару МБ.

+0

принимаю его в байтах? если я устанавливаю его на 450 кбайт, он работает для файлов размером менее 100 МБ. Но если они получат больше, у него снова есть поврежденные пакеты:/ –

+0

@StefanSprenger Я бы без колебаний установил его даже немного выше, например. 4MB. Затем вы можете оптимизировать производительность получающего приложения. При очень высоких скоростях даже System.out.println на каждом пакете может начать влиять на производительность. Кроме того, почему бы вам просто не выделить buf за один раз до цикла? – mac

+0

kk thx за вашу помощь –

 Смежные вопросы

  • Нет связанных вопросов^_^