wichtig Socketverbindung gesendete Bytes != empfangener

D

dto

(wichig für Diplomarbeit bitte um Hilfe)

ich verwendend schon seit einiger Zeit eine eigene Kommunikationsschnittstelle die über Sockets implementiert wurde.

der Sender sendet eine Datei in 4096 byte Stücken, der Empfänger weiß wieviel bytes er empfangen muss.

der Sender sendet wirklich immer genau die Größe die er soll.
aber in machen Situationen kommt beim Empfanger mal mehr mal weniger bytes an

Ich dachte eigentlich das dies mir TCP/IP regelt da es ja ein abgesichertes Prot. ist und java Socks darauf aufsetzen.

Kennt dieses Problem jemand
kennt einer die Lösung
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

hättest du evtl. etwas Source-Code ?

So den Code rund ums Senden und Empfangen ?

Denn sonnst geht das hier in die Richtung Kaffeesatz lesen !

Kann 1000 und einen Grund haben !

Gruß JAdix !
 
Einfach mal ins blaue geraten...mehr kann man ohne weiteres eh nicht machen...
...wenn du mit Strings arbeitest musst du drauf achten, dass wenn du die Bytes holst, dass diese in einem einheitlichen Charset encodierst/dekodierst.
 
nein ich versende keine Strings sondern direkt vom Stream der Datei

Sender
Java:
byte[] buffer = new byte[2048];
        
int nbytes = -1;       
            
FileInputStream data = new FileInputStream(file);

while ((nbytes = data.read(buffer)) != -1) {
                
    socketData.getOutputStream().write(buffer, 0, nbytes);
    socketData.getOutputStream().flush();
 }
                       
 data.close();

der Empfänger kennt durch ein übergeordnetes Protokoll die File.length() der gesendeten Datei

Java:
public void getFile(InputStream dataInputStream, String filename, long length, String destinationPath) throws Exception {
                                
        byte[] buffer = new byte[2048];
        int nbytes = - 1;
        
        new File(destinationPath + filename).createNewFile();
        FileOutputStream out = new FileOutputStream(destinationPath + filename);        
        
        for (long i = 0; i < length; i += nbytes) {            
            nbytes = dataInputStream.read(buffer);            
            out.write(buffer, 0, nbytes);                        
            out.flush();
        }        
               
        out.close();        
    }
 
der Empfänger weiß durch ein übergeordnetes Protokoll wieviel bytes versendet wurden also die File.length() des gesendeten Files und genau aus soviel byte wartet er auch und empfängt sie so

Java:
public void getFile(InputStream dataInputStream, String filename, long length, String destinationPath) throws Exception {
                                
        byte[] buffer = new byte[2048];
        int nbytes = - 1;
        
        new File(destinationPath + filename).createNewFile();
        FileOutputStream out = new FileOutputStream(destinationPath + filename);        
        
        for (long i = 0; i < length; i += nbytes) {            
            nbytes = dataInputStream.read(buffer);
            out.write(buffer, 0, nbytes);                        
            out.flush();
        }        
               
        out.close();        
    }

der Sender teilt dem Empfänger im durch ein übergeordnetes Protokoll mit wieviel bytes gesendet werden und dann sendet er so

Java:
byte[] buffer = new byte[2048];
        int nbytes = -1;
        try {
                                    
            FileInputStream data = new FileInputStream(file);
            while ((nbytes = data.read(buffer)) != -1) {
                                
                socketData.getOutputStream().write(buffer, 0, nbytes);
                socketData.getOutputStream().flush();
            }                        
                
            data.close();
            return 0;
        } catch (IOException ex) {
            return 1;
        }
 
Prüf mal mit available ob die bytes denn schon zur Verfügung stehen auf der Empfängerseite bevor du diese ausliest.
 
Hallo dontschew,

so schlecht sieht der Source nicht aus !

Das "i += nbytes" in einer for-Schleife find ich jetzt nicht so hübsch aber kann man ja mal machen.

Der vorschlag mit available bringt wahrscheinlich nicht so viel,
da in deinem Fall unwichtig ist ob zu einem bestimmten Zeitpunkt Daten abrufbar sind oder nicht.
Deine Schleife endet ja nicht wenn der read mal keine Daten liefert (EOF = -1) sondern erst wenn du deine fixe Größe an Bytes hast !
Und solange dein Code nich alternativ etwas anderes bearbeiten soll wenn keine Daten
vorhanden sind ist der available-Wert egal, der read blockt bis Daten da sind !

Woran erkennst du ob zuviele oder zuwenig Daten über den Stream kommen.
Gibt es irgendwie eine Exception, tauchen die Daten an anderer Stelle in deinem
Übertragungsprotokoll auf ?

Warum flush'st du so häufig ? Einmal nach der Schleife würde eigentlich reichen !

Gruß JAdix
 
Normalerweise flusht man nur vorm schliesen des Streams....was zum Beispiel bei socketData.getOutputStream() nicht stattfindet.

Aber mehr kann ich jetzt auch nicht sagen, dazu kenn ich mich zu wenig mit Sockets Streams aus.
 
Sorry das ich den Code 2 mal rein gestellt habe


Das "i += nbytes" in einer for-Schleife find ich jetzt nicht so hübsch aber kann man ja mal machen.

was ist der Grund für deine Meinung?

Und das read liefert nie EOF sonst müsste ich ja nicht alternativ auf Gesamtlänge prüfen. Muss ich beim Sender über einen bestimmten Stream senden um bei der Gegenstelle das EOF zu empfangen?

Mitbekommen hab ich das einfach durch Tests ich lass mir einfach zum Zeitpunkt des Empfangs ausgeben vieviel bytes ich momentan bekommen habe. Wenn zu wenig waren ist klar timeout und bei zu viel kann ich mit den übertragenen Daten nichts mehr anfangen. Da diese meist *.zip sind.

Eingebaut ist das ganze in einem verteiltem Rechensystem (run 40 Rechner) und dadurch treten natürlich massiv Verluste der einzellnen Arbeitspackete auf.

das komische ist auch wenn es zu viele sind ist das der Puffer am Ende immer ganz gefüllt. Zu wenig kann ich mir auch nicht erklären.
 
Zuletzt bearbeitet von einem Moderator:
Zusatz:

bei 1000 Übertragungen trit das Poblem vielleich 10-15 mal auf, lokal mit mehreren VM's nie
 
Zurück