Autor Beitrag
08/15
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 16.05.06 11:09 
Hallo Leute,

Hab hier nen kleinen Testaufbau stehen und eine Platine der Firma BECK@IPC versuche ich nun möglichst schnell mit dem Rechner reden zu lassen.
Eine Verbindung ist vorhanden, Leitung auf 100 Full Duplex und ich kann Daten senden und empfangen ... kein Problem soweit. Ich erzeuge nun dummydaten auf dem Chip und sende möglichst große Pakete and den Rechner per TCP/IP. Nur liegt mein Problem nun darin die Daten schnellstmöglich vom Socket zu bekommen. Ich komm bei meiner Zeitnahme ( passiert mit nem Hr timer auf dem chip ) auf gerade mal 1/10 der erforderlichen Bandbreite. Ich poste mal meinen Quellcode soweit hier und wollte Fragen ob ich was Grundlegendes übersehen hab dass meine Daten so langsam ankommen.

Achso ich hab auch schon per Udp vom Chip die Daten einfach mal ins Nirvana gejagt ... und dabei kommt ich auf das 9 Fache der geschwindigkeit gegenüber TCP. Also liegts an meinem Programm im Delphi. Ich nutz Delphi 7 :)
Achso und die Daten die kommen sind 120000 Bit und sollen ein 300*200 großes Bitmap befüllen.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
  private
    { Private-Deklarationen }
    FClientSock : TClientSocket;
    FRecvBuffer : Pointer;
    FRecvCount  : Integer;
    FBitmap : TBitmap;

procedure TfImpulsform.FormCreate(Sender: TObject);
begin
  FClientSock := TClientSocket.Create( Self );
  FClientSock.ClientType := ctNonBlocking;
  FClientSock.Host := edtIP.Text;
  FClientSock.Port := 7;
  FClientSock.OnRead  := Receiver;

  FBitmap := TBitmap.Create;
  FBitmap.PixelFormat := pf16bit;
  FBitmap.Width := 300;
  Fbitmap.Height := 200;

  AllocMemoryN( FRecvBuffer,  300*200*sizeof( Word ) + 1000 );
  FRecvCount  := 0;
end;

procedure TfImpulsform.Button2Click(Sender: TObject);
// Senden des EdtFensterinhaltes
var
  intReturnCode : integer;
  pch : array[0..240of Char;
  aPWs, aPWd : PWord;
  yy : Integer;
begin
  if FClientSock.Active then
  begin
    FRecvCount := 0;
    StrPCopy( pch, edSend.Text );

    intReturnCode := FClientSock.Socket.SendBuf( pch, Length(edSend.Text));
    if intReturnCode > 0 then
    begin
      StatBar( 0'Send' );
      StatBar( 1, IntToStr(FClientSock.Socket.RemotePort) );
      while FRecvCount < FBitmap.Width * FBitmap.Height * 2 do
      begin
        Application.ProcessMessages;
      end;
      aPWs := FRecvBuffer;
      for yy := 0 to FBitmap.Height-1 do
      begin
        aPWd := FBitmap.ScanLine[yy];
        CopyMemory( aPWd, aPWs, 600 );
        Inc(aPWs, 300 );
      end;
      Image1.Picture.Bitmap := FBitmap;
    end
    else
      MessageDlg('No answer from server', mtError, [mbOk], 0);
  end;
  StatBar(1'Ready' );
end;

procedure TfImpulsform.Receiver(Sender: TObject; aSocket: TCustomWinSocket );
var
  cnt : integer;
  pW : PByte;
begin
  cnt := aSocket.ReceiveLength;
  mmoReceived.Lines.Add( 'cnt: ' + IntToStr( cnt ) );
  if cnt > 0 then
  begin
    pW := FRecvBuffer;
    Inc( pW, FRecvCount );
    aSocket.ReceiveBuf( pW^, cnt );
    Inc( FRecvCount, cnt );
   StatBar(3, IntToStr( FRecvCount ) );
  end;
end;


Für Hilfe währe ich sehr dankbar weil erklären kann ich mir das ganze nicht :gruebel: oder ist es besser die TUdpSockUtil libary zu nutzen aus dem Forum hier ... aber vom Prinzip müsste doch TCP gut klappen.

Vielen Danke schonmal
Andreas
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 16.05.06 11:43 
Moin und :welcome: im Forum!

user profile icon08/15 hat folgendes geschrieben:
Ich erzeuge nun dummydaten auf dem Chip und sende möglichst große Pakete and den Rechner per TCP/IP.

Möglichst große Pakete korrelieren nicht mit hoher Übertragungsrate, weit verbreiteter Irrtum. ;) Meistens ist es wesentlich klüger, knapp unter MTU zu bleiben... :?

user profile icon08/15 hat folgendes geschrieben:
Ich komm bei meiner Zeitnahme ( passiert mit nem Hr timer auf dem chip ) auf gerade mal 1/10 der erforderlichen Bandbreite.

Sag doch mal Zahlen, relative Angaben helfen praktisch nicht. :gruebel: ;)

user profile icon08/15 hat folgendes geschrieben:
ich hab auch schon per Udp vom Chip die Daten einfach mal ins Nirvana gejagt ... und dabei kommt ich auf das 9 Fache der geschwindigkeit gegenüber TCP. Also liegts an meinem Programm im Delphi. Ich nutz Delphi 7 :)

Das ist möglicherweise nicht schlüssig bewiesen, s.o. ;)

Wenn du wirklich so nah am Grenzwert mit dem Timing hantierst (kann ich mir nur schwer vorstellen), dann solltest du sowieso besser einen Receiver-Thread abspalten und mit blocking-Sockets arbeiten, dass ist am schnellsten.

Weiterhin: der WSA-Buffer ist AFAIK 8kb gross, wenn du mehr am Stück sendest und mit asynchronen Ereignissen arbeitest, dann handelst du dir da möglichweise fett Wartezeiten ein.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
08/15 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 16.05.06 12:01 
Hehe danke für den Willkommensgruß

Ich hab in der Tat die Anbsicht die Daten so schnell wie möglich rüberzubekommen. Ich messe zur Zeit beim raussenden auf meinem chip 1190 CPU ticks was 1,19 sec entspricht. Bei 120000 / 1190 komme ich au 100,8 kB/s ... schaffen sollte das Protokoll laut hersteller in idealer Testumgebung aber 1085 kB/s. Das das nicht ganz zu erreichen ist erscheint mir logisch aber 10% von diesem Richtwert ist mir zu wenig :D

Die sache mit der Blockgröße ist so das ich wenn ich im OnReceive Ereignis in meine Quellcode bei maximaler Geschwindigkeit 1460er Blöcke eintrudeln ... das ganze 82 mal und noch ein kleiner 280er Block damit die 120000 komplett sind. Es kommt auch alles wie gewünscht an ... also die Daten sind stimmig. Wenn ich nun noch ein Sleep in OnReceive einfüge bekomm ich auch die maximalgröße von 8192 :) ... und ebenfalls verlustfrei alle Daten.

Wo verursach ich meine Wartezeit? Hab ich etwas nicht bedacht?

Danke für die schnelle Antwort
Gruß
Andreas

Edit: Wichtig ist auch das komplett alle Daten ankommen. Also fand ich TCP eher geeignet als wenn ich UDP nutze. Ich bin mit der überlegung rangegangen das ich die Puffer auf dem Chip vollschreib und dann rausschicke komplett ... so das sich das TCP protokoll schon darauf einstellt. Ich kann am Chip noch die Größe der Datenpackete einstellen oder verändern ... von 8192 auf 4096 oder noch geringer ... das bringt je kleiner diese werden jedoch nur nachteile in der Geschwindigkeit. Delphi scheint die 8192 als Standardwert irgendwo integriert zu haben wie mir scheint :gruebel:

Edti2: ( schnell noch ein Edit ;) ) Also die MTU liegt bei mir bei 1500 und ich hab nun meine Senddatenpakete auf 1024 gestellt ... die Geschwindigkeit ist konstant "langsam" ;) geblieben.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 16.05.06 13:54 
Moin!

user profile icon08/15 hat folgendes geschrieben:
Ich messe zur Zeit beim raussenden auf meinem chip 1190 CPU ticks was 1,19 sec entspricht. Bei 120000 / 1190 komme ich au 100,8 kB/s ... schaffen sollte das Protokoll laut hersteller in idealer Testumgebung aber 1085 kB/s. Das das nicht ganz zu erreichen ist erscheint mir logisch aber 10% von diesem Richtwert ist mir zu wenig :D

Ist das so ein embedded-device-server? Die sind nicht immer sooo schnell... Sicher, dass du die Doku korrekt verstanden hast (da die Werte ca. eine 10er-Potenz auseinanderliegen)? :mrgreen: (nicht aufregen bitte, wer nicht schonmal auf rtfm reingefallen ist, werfe den ersten Stein... ich hab hier nur Sand... ;))

user profile icon08/15 hat folgendes geschrieben:
Wo verursach ich meine Wartezeit? Hab ich etwas nicht bedacht?

Das AsyncSelect der WSA, was hinter den Ereignissen steckt, ist jetzt nicht gerade der Turbo... allerdings Faktor 10 Verlust wäre jetzt schon etwas sehr viel... :gruebel:

user profile icon08/15 hat folgendes geschrieben:
Wichtig ist auch das komplett alle Daten ankommen. Also fand ich TCP eher geeignet als wenn ich UDP nutze.

Hm, bei Bildern müssen wirklich immer alle Zeilen ankommen? :? Wenn du Einfluss auf das Protokoll hast, hätte ich sonst mal folgendes vorgeschlagen:
- nimm UDP (z.B. TUdpSockUtil ;))
- Bau die Pakete so auf: AppID | PictureID | LineNo | Data, also praktisch immer eine Image-Zeile pro UDP-Paket
- Rest (reassembling usw.) machste im Empfänger (Delphi)
- wenn was nicht angekommen sein sollte (kannste ja über die IDs rausfinden), forderst du diese Zeilen nochmal an
Zumindest einen Test wert, oder? ;)

user profile icon08/15 hat folgendes geschrieben:
Delphi scheint die 8192 als Standardwert irgendwo integriert zu haben wie mir scheint :gruebel:

Nicht Delphi, die WSA. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
08/15 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 16.05.06 17:01 
Danke für die kompetente Hilfe ... mein Fehler lag aber doch am Chip.
Der ist aber dermaßen trivial das ich mich net traue den hier zu sagen ;)

Also nochmal dickes Dankeschön
Gruß
Andreas