Hi,
ich versuche gerade, eine Datei (Binär) über Sockets zu übertragen.
Dabei stellen sich mir folgende Fragen:
Ich lese server-seitig eine Datei ein, z.B. 5672341 bytes. Laut Debugger
hat mein byte[] auch die richtige Größe. Mit Socket.Send übertrage ich dann
die Bytes, eingepackt in 1024 bytes großen Paketen. Jetzt kommen beim
Client aber ca. 500 bytes mehr an, als eigentlich die Datei groß ist. Ich habe
meinen Empfangspuffer nun mal auf 5672341 eingestellt. Die Datei wird
korrekt übertragen (binär identisch). Woher kommt also der Rest, zumal dieser
bei jeder Übertragung auch noch anders (in Größe und Inhalt) ist.
Woher erkenne ich, daß meine Nachricht nun zu Ende ist, welche Bytes
sind die Terminierung?
Gibt´s für Socket.Send auch so eine Art Flush? Wenn ich innerhalb einer
Funktion direkt hintereinander die Send-Methode aufrufe, werden diese nicht
als Einzelnachrichten abgesendet, sondern werden in die vorherige Nachricht
mit reingepackt, sofern da noch Platz ist.
Wäre super wenn mir jemand die Fragen beantworten könnte ...
Danke und Grüße,
wiesi
Servus,
ich vermute, dass die zusätzlichen Bytes von den Paketen selbst stammen. Du hast ja bei TCP/IP nicht nur Nutzdaten, sondern es werden auch Protokolldaten, Header und Checksummen gesendet.
Grüße Taggert
Moin
Ich denk mal dass es daran liegt:
5672341 /1024 = 5539,39550...
also brauchst du 5540 Packte a 1024 bytes um die Datei zu senden
5540*1024 = 5672960 Bytes
5672960 - 5672341 = 619
Du musstest also 619 bytes zusätzlich empfangen da das letzte 1024 bytes Packet nicht komplett mit den bytes aus der datei befüllt ist. wenn dir am anfang die grösse der datei überträgst kannst es damit dann abfangen, also du sagst dem client als erstes wie gross die datei denn sein wird.
wie gesagt ich denk mal dass es daran liegt, wenns ned stimmt bitte berichtigen
servus
Hallo,
bitte zeige mir deinen Empfangs, sowie Sendevorgang
(Socket.Receive, Socket.Send);
danke!
Mit freundlichem Gruß
info@smart-coding.com
www.smart-coding.com
Sorry mein Pc is grad am Arsch... ich werde den Code dann posten wenn er wieder geht.
Server:
Zuerst Dateigrösse in Byte[] umwandeln und an den Client schicken
while (readBytes < file.Length)
{
//Auslesen der Bytes aus Datei
length = m_FileStream.Read(this.m_bDataBuffer, 0, this.m_bDataBuffer.Length);
//Senden der Bytes an Client
this.m_soClientSocket.Send(this.m_bDataBuffer, length, SocketFlags.None);
Array.Clear(this.m_bDataBuffer, 0, this.m_bDataBuffer.Length);
readBytes = readBytes + length;
}
Client:
Dateigröße empfangen und Datei anlegen
lenght = 0;
while (readBytes < fileSize)
{
//Auslesen der Datenbytes aus dem Strem
length = this.m_soClientSocket.Receive(this.m_bDataBuffer, this.m_bDataBuffer.Length, SocketFlags.None);
//Schreiben in Datei
m_FileStream.Write(this.m_bDataBuffer, 0, length);
Array.Clear(this.m_bDataBuffer, 0, this.m_bDataBuffer.Length);
readBytes = readBytes + length;
}
Wenn Du große Dateien versenden willst dann benutze doch die asynchrone Send Funktion. Die payload Größe ist ja nicht unendlich groß. Kannst auch alles auf einmal senden, allerdings musst Du nach einem Send() überprüfen wieviele bytes tatsächlich gesendet wurden. Dann den offset zu Deinem Sendepuffer verschieben und so lange senden bis alles weg ist.
Eine TCP/IP Verbindung ist ein stream. Du fragst nach der Ende-Kennung für den Server? Schau Dir mal z. B. POP3 an, dort gibt es etwa CRLF.CRLF, allerdings als Ende-Kennung für den Client. Nun Du kannst auch "ja-ist-denn-heut-schon-weihnachten?" als Ende-Kennung definieren, oder Du sendest die Länge in einem header voraus (siehe HTTP Content-length).
yb~~~~~~~~~~~~
Du musst beim Empfänger nur die "Reste wegschneide.
Du Empfängst das ganze Datenfeld des TCP Packetes, egal ob du nun in 1024Byte oder 2Byte Schritten deine "Datenblocks" verschickst. Der TCP/IP Header ist ja so in etwa 1500KB lang. Ziehst die Headerinformationen (20Bytes glaub ich) ab und du hast die Datenlänge........
Hab das ganze mal mit WireShark getestet......eigentlich ganz einfach.
Beim Empfänger schneidest du die überresten ab (durch den "int" return der Receive Methode, hast du die Datenlänge..nachstehende Felder sind 0)
Noch einfacher wäre die Übertragung mit einem "Networkstream" (ich habs so gelöst)
Zur Kontrolle der Datenübertragung hab ich mir noch einen Header gebastelt, damit vor der Übertragung der MD5-Wert der zu sendenden Datei beim Empfänger hinterlegt ist = MD5-String vergleich 😁 ))
Gruss
stephan