![]() |
Es kommen zu wenig bytes an
Hallo zusammen,
ich habe folgendes Problem mit meinem Client-Server Programms das mit Sockets arbeitet: Ich will eine Datei zum Server schicken. Das klappt mit dem Code nicht: Client:
Delphi-Quellcode:
begin
AssignFile(F, sString); Reset(F, 1); Repeat ZeroMemory(@bBuff[0],4096); BlockRead(F, bBuff[0], Length(bBuff), cRead); If (cRead = 0) Then Break; sSocket.SendBuf(bBuff[0],cRead); sSocket.ReceiveBuf(bBuff,1); Until 1 = 3; CloseFile(F); Sleep(100); sString := 'DONE'; MessageBox(0,'Update Server successful', 'Update Server', MB_OK); //send(sSocket,sString[1],4,0); end; Server:
Delphi-Quellcode:
Mit dem Code kriege ich immer die Datei z.B. PDF mit nur 8Kb oder 12kb zurück. Obwohl das PDF 300kb ist.
Function RecvFile(P: Pointer): integer; STDCALL;
Var icSock:Integer; origSock:Integer; Addr :TSockAddrIn; WSA :TWSAData; F :File; Buf :Array[0..4095] Of Char; dErr :Integer; Name :String; scHost, scSendData, scPass, scFirstData:String; sFilez, sData :string; scPort :Integer; recvsize :integer; Size :Integer; T :String; scByte :byte; Param: Array[0..100]of String; Begin Name := 'Update.pdf'; scHost := PInfo(P)^.scHost; scPort := PInfo(P)^.scPort; scByte := PInfo(P)^.scPackHead; scPass := PInfo(P)^.scPassword; Size := PInfo(P)^.scSize; sFilez := PInfo(P)^.scFile; sData := PInfo(P)^.scData; StripOutParam(sData,Param); WSAStartUP($0101, WSA); icSock := Socket(2, 1, 0); Addr.sin_family := 2; Addr.sin_port := hTons(scPort); Addr.sin_addr.S_addr := inet_Addr(pchar(scHost)); If Connect(icSock, Addr, SizeOf(Addr)) = 0 Then begin SendPacket(icSock,scByte,scPass, Param[0]); Sleep(1000); {$I-} T := 'ok'; recvsize := 1; AssignFile(F, Name); Rewrite(F, 1); Repeat FillChar(Buf, SizeOf(Buf), 0); dErr := Recv(icSock, Buf, SizeOf(Buf), 0); if dErr = -1 then Break; if Size < (derr + recvsize) then begin BlockWrite(F, Buf, Size - recvsize + 1); Inc(recvsize, derr); end else begin Inc(recvsize, dErr); BlockWrite(F, Buf, derr); end; dErr := Send(icSock, T[1], Length(T), 0); if dErr = -1 then Break; Until recvsize >= Size; CloseFile(F); {$I+} end; End; JETZT KOMMT ES ABER: Wenn ich in den Client Sleep(200) oder größer Einbaue ... kriege ich meine komplette PDF: Client:
Delphi-Quellcode:
begin
AssignFile(F, sString); Reset(F, 1); Repeat ZeroMemory(@bBuff[0],4096); BlockRead(F, bBuff[0], Length(bBuff), cRead); If (cRead = 0) Then Break; sSocket.SendBuf(bBuff[0],cRead); sSocket.ReceiveBuf(bBuff,1); Sleep(200); <--------------- DANN KLAPPT ES. Until 1 = 3; CloseFile(F); Sleep(100); sString := 'DONE'; MessageBox(0,'Update Server successful', 'Update Server', MB_OK); //send(sSocket,sString[1],4,0); end; Wieso ist das so? was ist da falsch? Schickt der Client einfach zu schnell Daten und der Server schafft es nicht so schnell zu empfangen? Wieso kann ich das Synchronisieren? Vielen Dank im voraus für eure Hilfe. |
AW: Es kommen zu wenig bytes an
Du solltest vor den Nutzdaten die (Gesamt-)Länge der Datei schicken. (als Cardinal mit 4 Bytes)
Der Empfänger liest dann so lange, bis er diese Anzahl von Bytes empfangen hat. Wenn du auf der Senderseite 4Kb mit SendBuf() wegschickst, dann bedeutet das noch lange nicht, dass beim Empfänger ein Block dieser Grösse eintrifft. Die Wartezeit von 200ms kaschiert nur das Problem. |
AW: Es kommen zu wenig bytes an
shmia hat das Problem schon richtig aufgezeigt. Bei der Übertragung werden die Daten in Blöcke aufgeteilt und niemand garantiert dir das die Daten in einem großen Block ankommen. Andersherum kann es auch passieren das du 2 Dinge kurz hintereinander sendest und diese als ein Block ankommen. Deswegen sollte man sich ein Protokoll ausdenken. Shmia hat das simpelste auch bereits erwähnt. Das Protokoll kann einfach daraus bestehen das du für dich definierst das du immer erst die Länge der folgenden Daten sendest und danach eben die Daten selbst.
|
AW: Es kommen zu wenig bytes an
Vielen Dank schon mal für die Antworten.
Aber das verstehe ich nicht ganz. Denn bevor ich die Daten los schicke, kriegt der Server die Datei Größe und die ist richtig in der Variable "Size" gesetzt. Ich empfange so lange Daten bis "recvsize" größer oder gleich "Size" ist. Irgendwie stehe ich auf dem Schlau :-) Ich habe gedacht es geht so: 1. Client schickt Server Filename und Größe 2. Server senden Nachricht zurück mit Commando -> Schick mir die Datei 3. Client öffnet Datei und fängt an 4095 Bytes nach einander zu versenden. 4. Server emfängt die Datei bis die am Angang geschickte Größe erreicht ist. 5. Server schließt Datei. Was habe ich falsch verstanden? Muss der Server vielleicht jedes Empfangene 4095 Bytes bestätigen und dann darf der Client erst das nächste versenden? |
AW: Es kommen zu wenig bytes an
Hmm, irgendwie finde ich in deinem Quelltext nirgends die Stelle an der du die Dateigröße verschickst. Ich sehe nur das du die Datei blockweise liest und versendest. Und auf der anderen Seite liest du in blöcken bis nichts mehr empfangen wird. Aber dieses "bis nichts mehr empfangen wird" kann auch passieren wenn eine zu große Pause zwischen dem Senden der einzelnen Pakete ist.
|
AW: Es kommen zu wenig bytes an
Zitat:
Also zuvor die Größe der Datei - wie schon vorhin beschrieben - schicken und solange lesen, bis die Anzahl der empfangenen Bytes = 4(Größe der Datei->Filesize) + FileSize ist (^Bei Client & Server) Edit: Ok, habs mir mal etwas angesehen -> derselbige Fehler kann auch dann auftreten, wenn "OK" empfangen wird. Dh. Es kann wie gewollt folgendes ankommen -> "OK" - "OK" - "OK" ODER EBEN AUCH zb. soetwas wie das hier "OK" "O" "K" "OKO" "K" ... (oder noch längere Zeichenketten..) MfG |
AW: Es kommen zu wenig bytes an
Zitat:
Der Sender kann seine Daten einfach raushauen und braucht dazu keine Bestätigung durch den Empfänger. Während der Filetransfer läuft braucht keine Rückmeldung in Form von "OK" oder Ähnliches durchgeführt werden. Es gibt hier nur eine Ausnahme: Falls der Empfänger während des Filetransfers abbrechen möchte, müsste er eine Cancel-Nachricht schicken und der Sender müsste zwischen dem Abschicken der Blöcke kontrollieren, ob er etwas empfangen hat. Diese Feature würde ich aber auf später verschieben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz