Einzelnen Beitrag anzeigen

Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.679 Beiträge
 
Delphi 5 Professional
 
#6

AW: Schnellere Kommunikation mit einer Fritzbox

  Alt 13. Okt 2017, 16:42
Dass die Verbindung geschlossen wurde, erkennst du daran, dass MSDN-Library durchsuchenrecv() die Länge 0 zurückgibt.
Deswegen ja meine Änderung des Codes in die repeat -Schleife auf Basis des MS-Beispiels. Problem dabei: der zweite Schleifendurchlauf bleibt bei Aufruf der recv-Funktion stehen, d.h. die Verbindung wird eben nicht geschlossen, und der Aufruf von recv ist offensichtlich blockierend.

-----

Aber ich bin einen Schritt weiter. Mir ist aufgefallen, dass bei einem verkleinerten Sleep trotzdem teilweise noch Informationen ankommen, und zwar solche, die mittels POST in einem SOAP-Envelope angefragt wurden. Ein Blick in den Code offenbarte dann, dass bei solchen POST-Anfragen mit SOAP kein KeepAlive gesetzt wird, bei allen anderen schon:
Delphi-Quellcode:
function THTTPRequest.SendHeader: UTF8String;
[...]
      if Length(FHTTPSend.Soap.Namespace) = 0 then begin
        LHeader.Add(Format('Keep-Alive: %d', [KEEP_ALIVE]));
        LHeader.Add('Connection: Keep-Alive');
      end
      else
        LHeader.Add('Connection: Close');
Testweise habe ich die if-Bedingung auskommentiert und siehe da: es kommen alle Informationen an, auch mit einem Sleep(20); in TClient.ReceiveBuffer. Meine Schlussfolgerung: dem Server wurde im Header der Anfrage mitgeteilt, er soll die Verbindung offenhalten, was er offenbar auch tut. Deswegen wartet recv bis zum Empfang von Daten - also vermutlich "endlos".

Ich verstehe auch gar nicht, warum da ein KeepAlive angefordert wird. In THTTPRequest.Execute wird die Instanz von TClient unmittelbar nach dem Empfang der Daten sowieso zerstört - und der Socket damit ebenfalls geschlossen. Auszüge aus dem Code:
Delphi-Quellcode:
function THTTPRequest.Execute: Boolean;
[...]
SendStr := SendHeader + Params;
LClient := TClient.Create;
try
  if LClient.Connect then begin
    LClient.SendBuffer(SendStr, Length(SendStr));
    if (LClient.ReceiveBuffer > 0) then begin
      RcvdHeader(LClient.Header);
      RcvdContent(LClient.Content);
    end;
  end;
finally
  LClient.Free;
end;


destructor TClient.Destroy;
begin
  if FConnected then
      Disconnected;
  inherited;
end;

function TClient.Disconnected: Boolean;
begin
  Result := WinSock.shutdown(FSocket, SD_BOTH) = 0;
  if Result then begin
    FConnected := False;
    Result := WinSock.CloseSocket(FSocket) = 0;
  end;
end;
Wozu die Verbindung über KeepAlive offenhalten, wenn gleich danach der Socket geschlossen werden soll bzw. geschlossen wird

Grüße
Dalai
  Mit Zitat antworten Zitat