Autor Beitrag
HERB
Hält's aus hier
Beiträge: 9



BeitragVerfasst: Do 16.07.09 13:41 
Hallo
Ich habe einen SocketServer, der von einem SocketClient Daten empfangen kann. Dies klappt auch wunderbar, allerdings möchte ich nun einen Timeout einbauen.
Durch den Timeout soll der Datenempfang nur 3 Sekunden möglich sein. Falls in dieser Zeit keine Daten oder nicht alle Zeichen empfangen werden, soll das Empfangen abgebrochen werden.

Hier meine procedure Empfangen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
 procedure Empfangen(var Was: String);
  var
    iBuf : Byte;
    Buffer : array[0..256of Char;
    iTemp : Integer;
  begin
    Socket.ReceiveBuf(iBuf, 1);
    //TIMEOUT..
    if Socket.ReceiveBuf(Buffer, iBuf) <> iBuf then begin
      RAISE Exception.Create('Fehler');
    end
    SetLength(Was, iBuf);
    move(Buffer, Was[1], iBuf);
  end;
Niko S.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 566
Erhaltene Danke: 10

Win 7, Ubuntu
Lazarus, Turbo Delphi, Delphu 7 PE
BeitragVerfasst: Do 16.07.09 14:30 
Mein vorschlag wäre zu jedem "Clienten" eine zeit einzufügen in der das Paket angekommen ist ...
Und wenn das nächste Paket kommt wird das alte Paket gelöscht und das neue nicht als altes Paket behandelt sondern
als komplett neues.
Und wenn man jetzt sag ich mal prüfen will ob der nun nen DC hatte, dann kann man ja nen Timer im Hintergrund laufen lassen.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.07.09 14:49 
Moin und :welcome: im Forum!

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Durch den Timeout soll der Datenempfang nur 3 Sekunden möglich sein. Falls in dieser Zeit keine Daten oder nicht alle Zeichen empfangen werden, soll das Empfangen abgebrochen werden.
Kannst du mal näher erläutern, was das für einen Sinn hat? :gruebel: Einfacher Ansatz: Timer starten, im OnTimer den Socket deaktivieren. :nixweiss: Das wird aber möglicherweise "interessante" Effekte bringen und einen gerade laufenden Empfang auch nicht abbrechen... (das ist auch bei der WSA im non-blocking-mode nicht so einfach möglich) :?

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Hier meine procedure Empfangen:
Wo und wann wird sie denn aufgerufen?

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
 procedure Empfangen(var Was: String);
  var
    iBuf : Byte;
    Buffer : array[0..256of Char;
    iTemp : Integer;
  begin
    Socket.ReceiveBuf(iBuf, 1);
Woher weißt du, dass jetzt ein Zeichen zum Lesen anliegt? Was machst du, wenn du keines lesen konntest?

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
//TIMEOUT..
    if Socket.ReceiveBuf(Buffer, iBuf) <> iBuf then begin
Wer sagt, dass hier ein komplettes Paket angekommen ist oder immer ankommen konnte? Sind deine Pakete immer max. 256 Bytes groß? Selbst dann kannst du nicht davon ausgehen, dass ein SendBuf auch "alles" bei einem ReceiveBuf abliefert. :idea: Das hier halte ich für eine potentielle Konzept-Fehlerstelle!

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
RAISE Exception.Create('Fehler');
    end
    SetLength(Was, iBuf);
    move(Buffer, Was[1], iBuf);
  end;
Der lokale Buffer ist unnötig. Du kannst auch direkt in den String schreiben. ;)

cu
Narses

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



BeitragVerfasst: Do 16.07.09 15:16 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin und :welcome: im Forum!

Danke!

Die procedure "Empfangen" wird im "ServerSocket1ClientRead" aufgerufen, so hier:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
laenge := Socket.ReceiveLength;
    if laenge > 0 then begin
      try
        Empfangen(NawasEbenKommt); //und ich schicke max 256 zeichen!

Aber wie kann ich dann mit einem Timer absichern, dass ich bekomme was ich bekommen soll.
Brauche ich das überhaupt?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.07.09 16:40 
Moin!

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Die procedure "Empfangen" wird im "ServerSocket1ClientRead" aufgerufen, so hier:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
laenge := Socket.ReceiveLength;
    if laenge > 0 then begin
      try
        Empfangen(NawasEbenKommt); //und ich schicke max 256 zeichen!
.ReceiveLength liefert nicht zwangsweise die exakte Ansatz Bytes im Empfangsbuffer des Sockets (ich empfehle hier mal die API-Doku). Wenn das Ereignis eintritt, einfach Lesen und schauen, was der Functionsaufruf abliefert. :nixweiss:

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Aber wie kann ich dann mit einem Timer absichern, dass ich bekomme was ich bekommen soll.
Also mit einem Timer alleine und deinen Konzept-Bröckelchen gar nicht.

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Brauche ich das überhaupt?
Woher soll ich das wissen? Nochmal:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Kannst du mal näher erläutern, was das für einen Sinn hat? :gruebel:

cu
Narses

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



BeitragVerfasst: Do 16.07.09 16:55 
Also, erstmal danke, dass Du so schnell antwortest!

Nun zum Problem:
Ich habe eine Anwendung, die einen SocketServer hat. Dieser SocketServer erhält Daten von einem Client (3 verschiedene Parameter).
Wenn ich alle 3 Parameter über meine procedure "Empfangen" erhalten habe, rufe ich eine URL auf (3.Parameter).
Nun will ich aber Timeouts einbauen, damit falls ein Client das Senden mittendrin abbricht, dass ich dies abfangen kann, und den User darüber informieren kann.
Danach soll der Server wieder bereit sein zum Empfang.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.07.09 17:09 
Moin!

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe eine Anwendung, die einen SocketServer hat. Dieser SocketServer erhält Daten von einem Client (3 verschiedene Parameter).
Wenn ich alle 3 Parameter über meine procedure "Empfangen" erhalten habe, rufe ich eine URL auf (3.Parameter).
Nun will ich aber Timeouts einbauen, damit falls ein Client das Senden mittendrin abbricht, dass ich dies abfangen kann, und den User darüber informieren kann.
Bei einer TCP-Verbindung rechnest du mit einem verdeckten Abbruch bzw. einen unvollständigen Sendevorgang? :shock: Was machst du da bloß... :gruebel:

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Danach soll der Server wieder bereit sein zum Empfang.
Ich habe den leisen Verdacht, du hast keine Ahnung, wie die Socket-API(WSA) bzw. TCP konzipiert ist, kann das sein? :?

Ich denke, du solltest dir mal dieses Tutorial ansehen, das hilft sicher weiter. :les: :think: ;)

cu
Narses

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



BeitragVerfasst: Fr 17.07.09 13:22 
Tja dann sage ich mal entschuldigung für meine Unwissenheit.

Jedoch schicke ich so wie ich empfange, was die Sache bestimmt nicht besser macht, aber mit dem Code oben klappt es bisher immer.

Gut ich habe noch nen Sleep eingebaut hier->
ausblenden Delphi-Quelltext
1:
2:
3:
begin
  Sleep(500)
  Socket.ReceiveBuf(iBuf, 1);

Selbst wenn ich von mehreren Clients Daten schicke, kommt das an, was ankommen soll.
Die Sache mit dem Timeout lasse ich nun einfach.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 17.07.09 13:30 
Moin!

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Tja dann sage ich mal entschuldigung für meine Unwissenheit.
Kein Grund zur Entschuldigung :nixweiss: sondern zum Nachholen. :zustimm:

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Jedoch schicke ich so wie ich empfange, was die Sache bestimmt nicht besser macht, aber mit dem Code oben klappt es bisher immer.
Empirischer Programmierstil ("funktioniert-doch-Code") ist kein Ersatz für ein vernünftiges Konzept (hier: Protokoll), das sollte klar sein. :?

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Gut ich habe noch nen Sleep eingebaut hier->
ausblenden Delphi-Quelltext
1:
2:
3:
begin
  Sleep(500)
  Socket.ReceiveBuf(iBuf, 1);

Selbst wenn ich von mehreren Clients Daten schicke, kommt das an, was ankommen soll.
Das ist keine Lösung, geschweige denn verdient es kaum den Namen "Workaround". Wenn du es sauber machen willst, nimm ein Protokoll mit entsprechend konzipierten Sende/Empfangsmethoden. Damit ist sowas wie dein "Sleep"-Ansatz schlicht überflüssig. ;)

user profile iconHERB hat folgendes geschrieben Zum zitierten Posting springen:
Die Sache mit dem Timeout lasse ich nun einfach.
Ja, würde ich auch vorschlagen.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.