Einzelnen Beitrag anzeigen

Gimp

Registriert seit: 28. Dez 2007
7 Beiträge
 
Delphi 2006 Personal
 
#5

AW: TServerThread.ClientExecute; Buffer Problem

  Alt 5. Okt 2011, 02:51
Mhm, unbedingt auf jedes Paket antworten zu müssen finde ich nicht gerade optimal. Sende ich im Clienten in einer while Schleife ohne Sleep() Pakete, kommen falsche Daten an. Ich denke, der ClientSocket schafft es nicht, die ganzen Daten so schnell zu senden, der Server Part sollte denke ich für einen kleinen Test und weck vom copy pasta Code aus dem Internet soweit in Ordnung sein. Zumindest wüsste ich nicht, wo sich hier noch ein Fehler verstecken könnte. Der Client sendet die Daten sehr simpel über Socket.SendBuf(...), gibt es da ab einer gewissen Geschwindigkeit Probleme?

edit: Die Pakete sind nie größer als 100~ Bytes, ein size als Byte reichte mir also im Paket Header

Delphi-Quellcode:
procedure TServerThread.ClientExecute;
type
  PClientPacket = ^TClientPacket;
  TClientPacket = packed record
    ID : Byte;
    Size : Byte;
  end;
var
  readlen, readpos: Integer;
  fRequest: Array[0..1023] of Byte;
  clientPacket: TClientPacket;
const
  timeout = 30 * 1000;

  CPKT_TEST = 1; // Client-Paket 1
  CPKT_TEST2 = 2; // Client-Paket 2
begin
  inherited FreeOnTerminate := true;

  fSocketStream := TWinSocketStream.Create(ClientSocket, timeout);
  try
    while (not Terminated) and (ClientSocket.Connected) do
    begin
      try
        if (fSocketStream.WaitForData(timeout)) then
        begin
          readpos := 0;
          FillChar(fRequest, 1024, 0);
          readlen := fSocketStream.Read(fRequest, 1024);

          while (readlen - readpos > 0) do
          begin
            if (readlen - readpos < SizeOf(TClientPacket)) then
            begin
              // kein header
              break;
            end;

            clientPacket := PClientPacket(@fRequest[readpos]))^;
            {$IFDEF DEBUG}
            MessageBox(0, PChar('packet code: ' + IntToStr(clientPacket.ID) + ' size: ' + IntToStr(clientpacket.Size)), nil, 0);
            {$ENDIF}

            case clientPacket.ID of
              CPKT_TEST: ;
              CPKT_TEST2: ;
            else
              MessageBox(0, PChar('Ungültigen Paket Code (' + IntToStr(clientPacket.ID) + ') empfangen!'), nil, 0);
            end;

            inc(readPos, clientPacket.Size + SizeOf(TClientPacket));
          end;
        end;
      except
        on E:Exception do
        begin
          ClientSocket.Close();
          Terminate();
        end;
      end;
    end;
  finally
    fSocketStream.Free();
  end;
end;
Nach einigen Paketen wird bereits die MessageBox aufgerufen, welche mir mitteilt das ein ungültiges Paket übertragen wurde. Setze ich im Clienten ein kleines Sleep passiert dies nicht.

Der Client, welcher stupide 2 unterschiedliche Pakete in einer while Schleife sendet:

Delphi-Quellcode:
var
  // paket code (1, 2), restliche grö0e, daten
  buf1: Array[0..9] of Byte = (1, 8, 1, 2, 3, 4, 5, 6, 7, 8);
  buf2: Array[0..7] of Byte = (2, 6, 1, 2, 3, 4, 5, 6);

procedure TForm1.Button2Click(Sender: TObject);
begin
  while true do
  begin
    ClientSocket1.Socket.SendBuf(buf1[0], Length(buf1));
    ClientSocket1.Socket.SendBuf(buf2[0], Length(buf2));
  end;
end;
edit: Nach dem ich nun die Buffergröße etwas angehoben habe, klappt es wie gewünscht Ok... mein PC friert fast ein bei der Masse an Kommunikation, aber scheint soweit sehr stabil. Bin gespannt ob der Client die Daten auch so einfach fressen wird, welche vom Server kommen. Danke nochmal Sir Rufo

edit 2: Den sendbuf Fehler habe ich auch eingesehen, ich hoffe die folgende Funktion ist so korrekt, zumindest gab es mit mehreren Clients und einer while Schleife keine Übertragungsfehler. Ich werde mich jetzt mal dransetzen und daraus eine sorgfältigere Umsetzung basteln

Delphi-Quellcode:
procedure SendPacket(pData: Pointer; iLength: Integer);
var
  nSentBytes: Integer;
  buffer: Array of Byte;
begin
  nSentBytes := 0;

  SetLength(buffer, iLength);
  Move(pData^, buffer[0], iLength);

  while (nSentBytes < nLength) do
  begin
    nSentBytes := Form1.ClientSocket1.Socket.SendBuf(buffer[nSentBytes], iLength - nSentBytes);

    if (nSentBytes = SOCKET_ERROR) then
      break;
  end;
end;

Geändert von Gimp ( 5. Okt 2011 um 06:26 Uhr) Grund: Leicht überarbeiteter Code, Client Part hinzugefügt
  Mit Zitat antworten Zitat