aufgabe 7


Hast du auch geschaut ob du in beide Richtungen lesen und schreiben kannst?
Ich hatte das auch vergessen und beim Browser blieb dann immer nur eine leere Seite.


naja wenn ich in die eine richtung lesen kann und in die andere schreiben (was ich halt prüfe), dann les ich aus der einen und schreib auf die andere mit read und write.

in eine richtung gleichzeitig lesen und schreiben geht doch nicht, oder?

achja wenn ich lese muss ich ja in nen buffer reinlesen, wie groß solld er denn sein und welcher art ? bei mir ist das ein char-buffer… liegt da der fehler?


Naje, wenn du von fd1 lesen und fd2 schreiben geht, dann machste das halt. Und andersrum halt auch (Huh?)

Ich hab auch nen char buffer und bei mir funzts.


Ist das in dem Fall nicht egal? Wenn forward() beendet, machst du die Sockets zu. Ob nun ein Fehler war oder nicht, die Reaktion ist doch die gleiche.


Sicher? Also ich hab eher den Eindruck, dass eine Verbindung mit 2 Endpunkten eindeutig durch die beiden Adressen mit ihren Port-Nummern beschrieben wird. Also: Der Server hört auf einer festen IP auf Port 80. Alle eingehenden Verbindungen kommen von unterschiedlichen Adressen (Clients). Wenn ein Client 2 Verbindungen aufbaut, wird er dabei 2 verschiedene Port-Nummern seinerseits verwenden (die so ab 1300 rum…). Damit gibt’s überhaupt kein Problem, dass da was nicht eindeutig wäre. netstat zeigt ja schließlich auch Verbindungen zu Port 80 (http) an, und nicht zu irgendwelchen ausgehandelten Ports.

Die mehreren Prozesse braucht’s dann nur zum gleichzeitigen Behandeln mehrerer unabhängiger Verbindungen.

Solche Fragen hab ich mir damals auch gestellt, als ich mit Sockets angefangen hab und mir das alles recht undurchschaubar vorkam. Allerdings ist doch der wichtigste Prozess dabei, dass beim connect() ein freier Port auf dem lokalen System ausgewählt wird, von dem aus dann verbunden wird. So kann es überhaupt keine ‚doppelten Zeilen im unique index‘ geben.

Ich lass mich aber gerne eines besseren belehren, wenn das jetzt totaler Quak war.

seitenaufbau endet nach bestimmter zeit
bei uns ist folgendes problem:
der seitenaufbau des browsers wird immer langsamer und endet nach kurzer zeit und die meldung
“Connection to host www.blabla is broken”
ausserdem gibt das programm aus: “accept: Bad File Descriptor” .

Und nochwas, die uni-seiten gehen ohne probleme…


Hi Yves,

Hmm - du setzt einen Layer zu tief an, denn natürlich kann es mehrere TCP-Verbindungen über einen IP-Port geben. IP ist das Protokoll, in das die TCP-/ oder UDP-Pakete mit ihren Sockets eingepackt werden. IP kennt nur 65535 Ports (oder eben den Port 80), ist aber nicht verbindungsorientiert. TCP ist das sehr wohl und darum gibts auch für jede TCP-Verbindung einen Socket und zwar soviele, wie Filedescriptoren nutzbar sind.

Also… du horchst an deinem IP-Port 80, ob dir einer TCP-Pakete schickt, freust dich wenn was kommt, machst nen neuen TCP-Socket (durch das accept) und unterhältst dich mit dem Teilnehmer (mittels TCP-Paketen, die in IP-Pakete verpackt und von Port zu Port geschickt werden), horchst aber währenddessen auf dem alten Socket weiter.

Wie gesagt - TCP und IP sollte man nicht verwechseln :smiley:


Schon, aber ist das neue Socket nicht auch mit Port 80 verbunden? Also ‚verbunden‘, denn es ist ja nicht ‚verbunden‘ :wink: Mit bind() mein ich jetzt. Es sollte nachher also 2 Sockets geben, die Daten über ihren Port 80 ‚austauschen‘, nur eins der beiden wartet halt auf neue Verbindungen (listen) und bekommt sie eben auch vom OS (bind). Jedenfalls geht meine Client-Verbindung zum HTTP auch während der Verbindung auf den Port 80.

Ein fiktiver Auszug aus der TCP-Tabelle wäre dann (aus Sicht des Servers)
[m]FD local_host local_port ↔ remote_host remote_port status
3 faui09b 80 * * listen
4 faui09b 80 dialin.t-online.de 4256 connect
7 faui09b 80 faui05c 2361 connect[/m]


Das stimmt nicht und ein Webserver funktioniert auch nicht wie von dir beschrieben. Ein Socket wird durch vier Werte bestimmt: Src-Adresse, Src-Port, Ziel-Adresse, Ziel-Port. Der Ziel-Port und die Ziel-Adresse koennen durchaus immer gleich sein ohne sich dadurch auf eine Verbindung zu beschraenken.

Was ihr meint ist das das Kind, das die Daten an den entfernten Rechner weiterleitet, einen anderen Socket mit einem anderen Src-Port braucht


Wie das der TCP/IP-Stack jetzt so wirklich macht, kann euch doch eigentlich egal sein, naja sei’s drum, des ist schlieslich OTRS3 Stoff.
Der kriegt halt IP Pakete, identifiziert die anhand des IP und tcp bzw. udp headers (siehe swarsrons post), bei tcp baut er sie erst noch in richtiger Reihenfolge zusammen, bzw fordert sie neu an, bei udp reicht er sie einfach an den buffer des filedescriptors weiter. Daraus kriegt ihr sie mit read raus, bzw schreibt sie mit write rein.

Jedenfalls kriegt ihr beliebig viele eingehende Verbindungen mit accept, muesst fuer jede eine eigene Verbindung mit connect aufmachen.

In dieser Verbindung muesst ihr quasi-gleichzeitig in beide Richtungen lesen und schreiben.
Warum das?
Man weiss ja nicht, wenn man einfach abwechselnd von A nach B und dann wieder von B nach A kopiert, ob das nicht beim ersten schon haengt, weil A gerade auf etwas von B wartet (waehrend ihr im read so lange wartet, bis A etwas schickt). Um nicht haengen zu bleiben gibts drei Moeglichkeiten:

  • bei open kann man ein flag O_NONBLOCK angeben, fuer unsere sockets nutzt uns des reichlich wenig
  • fuer jede Verbindung einen Prozess forken
  • die einzig wirklich gute Lsg. dafuer ist mit Hilfe von select

Wie das geht?
Ihr lasst den select durchlaufen, dann wisst ihr wer lese- und wer schreib-fertig ist, und dann kann man dementsprechend in die eine oder die andere Richtung schreiben.


Wenn man auf die man-page von select schaut, dann wird am Ende auf eine weitere man-page verwiesen, in der ein ausführliches Beispiel steht. Es kann doch nicht verboten sein, dieses als Vorlage zu benutzen, oder ?!? (Bitte jetzt keine 0 Punkte :rolleyes: )


nur ein kleiner hinweis, select() fragt nicht, wie es hier irgendwo steht, permanent irgendwelche filedeskriptoren ab.
ferner ist es so, dass select den prozess in den schlafzustand versetzt und er vom kernel aufgeweckt wird, sobald sich etwas an einem der deskriptoren “zum guten hin” :wink: ändert…

mit blocking sockets und select zu arbeiten ist IMHO erheblich sauberer, als mit nonblocking und while schleifen…