Aufgabe 8


Zurueck zur Aufgabe :cheesy:

Ich hab u. a.
sock = socket(…);
(connect(sock, …, …)

Der Errno “operation on non-socket” kommt bei connect und ich hab keine Ahnung warum. Irgendwelche Vorschlaege? :-/


Vielleicht wären die Sock-Optionen nicht schlecht zu wissen, da kann auch der Fehler sein!

Ansonsten…


   (sock = socket(AF_INET, SOCK_STREAM, 0):
   host = gethostbyname(destination);
    memset(&san, 0, sizeof(san));
    memcpy( (char *) &san.sin_addr, (char *) host->h_addr, host->h_length);
    san.sin_family = AF_INET;
    san.sin_port = htons(port);
    if( (connect(sock, (struct sockaddr*) &san, sizeof(san))) != 0)
    {
            perror("Failed to Connect...");                                 return -1;
    }

Biite :-/


Es fehlt zwar immer noch ein bisschen der Zusammenhang (: → Ist das Ganze in einem switch?!), aber socket() liefert dir bei einem Fehler nicht 0 sondern -1, vielleicht war’s das?


Gut hat ich schon == -1, hab es dann in != 0 abgeaendert da es im erfolgsfall 0 returned. Stimmt der Zusammenhang. :wink: Ich hab jetzt ein Client Socket und moechte jetzt auf den Uebergebenen Host/Server connecten. Das ganze ist kein Swich, sondern eine Alleinstehende Funktion mit demeinsprechenden Parametern :wink:


Verwirrt hat mich halt der Doppelpunkt nach dem socket(), weil a) a ? b : c passt net b) Label? Nö. c) switch… Und da würde dann der Rückgabewert nicht dazupassen…

Naja, jetzt muss ich jedenfalls erstmal weg… :slight_smile:


der ist unabsichtlich im Forum reingekommen :wink:


Du musst ja fuer jeden Verbindungsaufbau ein Kind wegforken. Es ist wichtig, dass Du in dem Kind auch jeweils wieder einen neuen socket erzeugst, spricht
das socket(…) gehoert genauso wie das connect hinter den fork. Ansonsten sieht es auch korrekt aus.

Noch eine Kleinigkeit: Beim Anlegen eines socket spezifiziert man die Protokollfamilie/Domain des sockets, also fuer IP steckt man da PF_INET rein, nicht AF_INET. Die Addressfamilie innerhalb der Protokollfamilie wird dann erst beim Binden bzw connect angegeben, um den Typ der Adresse an die gebunden bzw zu der verbunden werden soll anzugeben, also in die struct sockaddr_in kommt dann AF_INET in das sa_family Feld. Funktionieren sollte es mit Deiner Loesung auch, weil AF_INET und PF_INET auf die gleichen Werte definiert sind, ist allerdings konzeptionell nicht ganz richtig.

Auszug socket.h:

bits/socket.h:#define   PF_INET         2       /* IP protocol family.  */
bits/socket.h:#define   AF_INET         PF_INET

Danke. Soweit mit forken sind wir noch nicht. Wir haengen gerad an der ersten Teilaufgabe. :-/
→ Failed to Connect…: Socket operation on non-socket
Wenn man mal die Errno interpretiert heist das wohl das unser socket() irgendwie schief geht oder falsch ist?


Ja das heisst einfach die Zahl die ihr dem connect als socket gebt ist kein socket :slight_smile: Und das passiert normalerweise, wenn der socket() Aufruf fehlt oder schief geht. Mit einer entsprechenden Fehlerpruefung um den socket() Aufruf sollte man das aber auch merken…


Mit tatkraeftiger Unterstuetzung der Uni Wuerzburg haben wirs gefixed. Tolle Klammerfehler :-/ Thx for all


Wie viele Threads braucht man eigentlich?
So wie ich das sehe braucht man ein Thread der vom fd1 liest und einen anderen der auf den fd2 schreibt. Aber, so funktioniert, dass ja dann nur in eine Richtung. Sollte man jetzt noch 2 weitere Threads erstellen die das selbe in die umgekehrte Richtung machen, oder einfach den 1Thread von beiden lesen lassen und den 2Thread schreiben lassen?


Du kannst in einem Thread von fd1 lesen und das, was du gelesen hast, auf fd2 schreiben. Und im zweiten Thread machst du das Ganze dann andersrum.


Darf man des so simpel machen?

Weil eigentlich is das ja im groben die nächste Aufgabe, aber in der Angabe steht doch “Implementieren Sie die Funktion forward nun selbst” und in der forward.h “Die Funktion liest sowohl von fd1 wie auch von fd2 Daten in einen internen Puffer und schreibt diese Daten auf dem jeweilig anderen Filedescriptor wieder raus.”

Muss ich jetzt hier auch schon einen Ringpuffer einbauen?!


Es macht keinen Sinn fuer eine Richtung zwei Threads laufen zu lassen - der Schreiber haette ja nie etwas zu tun so lange der Leser auf Daten wartet, und umgekehrt koennte der Leser nichts neues lesen solange der Schreiber den Puffer nicht freigeraeumt hat. Dass die Daten in einen Internen Puffer wandern muessen ist auch klar, denn schliesslich gibt es keinen Syscall der
Daten von einem Filedeskriptor ohne Zwischenspeicher in einen anderen
schaufelt.
Einfach dargestellt eben so:

char puffer[1024];
int bread;
while(1) {
   bread = read(from, puffer, 1024);
   write(to, puffer, bread);
}

In der forward.h steht was das ich nicht versteh:

Ob ein deskriptor geschlossen ist kann man doch nur festststellen,
wenn read() mit -1 zurückkehrt und ernno gleich EBADF ist oder?
Nur wenn jetz in einem der beiden Threads das der Fall ist dann sollte forward zurück kehren.

Jetz schliesst aber weder der Proxy noch z.b. der Webbrowser irgendwelche Deskriptoren…
folglich würde die funktion ja nicht zurückkehren, was sie aber tut.
Meiner meinung nach muss doch die forward zurückkehren wenn read() 0(EOF) zurückgibt und beide threads das einmal gelesen haben?

Würde das gern mal in erfahrung bringen, da die Variante mit dem zurückkehren falls ein deskriptor geschlossen wurde
bei meinem Programm hier überhaupt nicht funktioniert.
Ich habe deshalb nach kurzer zeit hunderte threads die alle wie wild in ner schleife hängen wo read immer mit 0 zurückkommt.

Auch die andere Variante ist nicht wirklich 100 prozentig zuverlässig,
was vielleicht an synchronisationsproblemen liegt auf die ich jetz nicht komm.

Bitte helft mir mal, ich hab schon genug zeit dammit verplämpert.

thx


Ok ich hab mein Problem jetz selber gelöst. :smiley:

Ein aufruf von select(…) an der richtigen stelle hat mir gezeigt dass read() auch EOF, also 0, liest wenn der Deskriptor geschlossen wurde.

Das entscheidende war jetz das codestück:

ret = read(...);
if (ret == 0)
  exit(0);

Es muss an der stelle ein exit() sein und kein pthread_exit() oder return,
weil es nicht immer garantiert ist dass beide seiten ihre deskriptoren schliessen.
Wenn man in der forward() funktion mit pthread_join() auf die beiden threads wartet,
dann kommt man da nie wieder raus wenn ein thread nicht terminiert, also der deskriptor nicht geschlossen wird.

mit exit() aber schiesst man dann den ganzen Prozess ab egal was der andere deskriptor macht und die sache ist gegessen.
Das forward verhält sich dann genauso wie im header beschrie :gun: ben

Bitte korrigieren fals ich hier schmarrn erzähl :cool:

?
Naja ich weiß ja nicht was du in deinem Code machst - aber ich habe eben so lange gelesen bis nicht mehr gekommen ist und dann hat sich die Funktion ganz normal über “ret” beendet.
Keinerlei select und Konsorten…


man 2 shutdown kommt gut wenn man schön aufräumen will.


[offtopic]
Pah, wie sie jetzt alle still sind… xD
[/offtopic]