{  Joachim Deckers  Anlage zur 2. Staatsexamensarbeit / 28.5.96  Lösungsvorschlag zu den Aufgaben 8 und 9 im Abschnitt  "7.3.5.4 Fragmentierung und paketweise Übermittlung"  Die Verwendung einer Unit wird in den Aufgaben zwar nicht gefordert,  erscheint aber zweckmäßig, wenn den Schülerinnen und Schülern der  Umgang mit Units vertraut ist.}unit protp3;INTERFACEtype      kennung = byte;const     Feldgroesse = 100; { Größe eines Datenpaketes                               (inkl. Protokollkopf) }procedure SendePkte(von, an: kennung; laenge: Word; feld: PChar);function  EmpfangePkte(    ich: kennung;                             var von: kennung;                       var laenge: word;                           feldgroesse: word;    { Größe des Feldes für die Nachricht }                                feld: PChar): boolean;{ Feld für die Nachricht }IMPLEMENTATIONuses  protokoll, protp2, strings,      WinCRT;const ProtKenn     = 'P'#3;      ProtOverhead = 2 + 4;        { Zusätzliche Bytes für Pakettransfer }      MaximalePaketLaenge = Feldgroesse - ProtOverhead;                                   { Overhead des Protokolls P2 wird                                     nicht berücksichtigt (die Paketlänge                                     ist hier also die Länge der Nachricht                                     für P2) }                                                                          procedure SendePkte(von, an: kennung; laenge: Word; feld: PChar);var lfdNr, insgesamt, pos: Word;    s       : string;begin  insgesamt := (laenge div MaximalePaketLaenge) + 1;  { Zuerst haben alle Pakete die gleiche Länge }   for lfdNr:=1 to insgesamt-1 do begin     pos:=(lfdNr-1)*MaximalePaketLaenge;     PCharInString(MaximalePaketLaenge,@feld[pos],s);     s:=ProtKenn+word2string2(lfdNr)+word2string2(insgesamt-lfdNr)+s;     { Laufende Nummer und Anzahl noch ausstehender Pakete davorschreiben }     SendeP(von,an,s);     { Und jetzt noch 10 Zentisekunden = 0,1 Sekunde warten,       damit ggf. auch andere Prozesse ihre Nachrichten schicken       können. Gehört nicht zur Aufgabenstellung, ist sinnvoll,       wenn die Protokolldatei nicht auf einem Netzwerkserver liegt. }     Warte(10);  end;  { Das letzte Paket könnte kürzer sein }  pos:=(insgesamt-1)*MaximalePaketLaenge;  PCharInString(laenge - pos,@feld[pos],s);  s:=ProtKenn+word2string2(insgesamt)+word2string2(0)+s; { Laufende Nummer und Anzahl noch ausstehender Pakete davorschreiben }  SendeP(von,an,s);end;function  EmpfangePkte(ich: kennung; var von: kennung; var laenge: word; feldgroesse: word; feld: PChar): boolean;var nochzuempfangen,    lfdNr, letzteNr,    nachrlaenge,    anzahl             : word;    s                  : string;    absender           : kennung;    fehler             : boolean;  function min(a,b:integer):integer;  begin    if a<b then min:=a else min:=b  end;       begin  letzteNr:=0;  laenge  :=0;  fehler:=NOT EmpfangeP(ich, absender, s);  if (s<>'') then begin    von:=absender;    if not fehler then    repeat      if Copy(s,1,2) = ProtKenn then begin         lfdNr:=char2word(s[3],s[4]); { laufende Nummer auslesen }        if lfdNr<>letzteNr+1 then begin          fehler:=true;          writeln('Fehler: Paket ',lfdNr,' nach Paket ',letzteNr,' erhalten.');        end        else begin          letzteNr       :=lfdNr;                 { für das nächste Paket merken       }          nochzuempfangen:=char2word(s[5],s[6]);  { wieviele Pakete noch? (0 = fertig) }          anzahl         :=Length(s)-ProtOverhead;          if (laenge+anzahl)<feldgroesse then     { Paßt es noch ins Feld? }             StrPCopy(@feld[laenge],Copy(s,7,anzahl));          inc(laenge,anzahl);                     { anzahl hochzählen }          if nochzuempfangen>0 then               { ggf. nächstes Paket holen }            fehler := NOT EmpfangeP(ich,absender,s);        end;      end      else        fehler:=true; { Keine Protokollkennung gefunden }     until fehler or (von<>absender) or (laenge=feldgroesse-1) or (nochzuempfangen=0) or (s='');    if (nochzuempfangen=0) and   { alle Pakete erhalten,       }       (von=absender) and        { immer vom gleichen Absender,}       (laenge<feldgroesse) and  { Nachricht paßte in das Feld }       not fehler then           { und sonst kein Fehler       }      EmpfangePkte:=true         { => Nachricht kann verwendet werden   }    else      EmpfangePkte:=false        { => Fehler, Nachricht nicht verwenden }  end { if s<>'' then ... }  else begin { leere Nachricht erhalten, kein Fehler }    EmpfangePkte := true;    laenge:=0;  end;end;beginend.
