Socketserver; TCP/IP; pTHreads

Genius

Mitglied
Hallo liebe Community,

ich bin gerade dabei einen Socketserver + Client (TCP/IP) zu programmieren und habe noch einige grundsätzliche Fragen und werde bestimmt auch noch in kommender Zeit einige weiter Fragen haben, deswegen erstelle ich diesen Thread. Bin gerade erst dabei, mich in die Materie einzuarbeiten.

1. Kann ich ausschließen, dass es zu 0/1 Verdrehern kommt?
Beispiel:
Code:
Client:
send(socket, „123\0“, 4, 0);
Server:
recv(socket, char, 4, 0);
printf(„%s\n“, char); => gibt zum Beispiel 112 aus
3. Ist malloc sehr rechenintensiv? Ich arbeite mit pThreads und da ist die Frage, ob ich jedem Thread von Anfang an einen gewissen Platz im Stack freihalte oder je nach Bedarf mit malloc akquiriere. Ich möchte nicht, dass mein Server eine lahme Schnecke wird, weil er ständig damit beschäftigt ist den Speicher neu zu verwalten.

4. Wenn ein pThread (Serverseitig) gerade nichts für seinen Client tun kann, würde ich ihn gerne um Ressourcen zu sparen so lange mit pthread_cond_wait warten lassen.
Ist es möglich, dass der Client das pthread_cond_signal an den ja eigentlich schlafenden Thread sendet um ihn wieder aufzuwecken, wenn der Server dem Client vorher seine Adresse verrät? Dürfte ja eigentlich nicht gehen, da der Thread, der auf den Client hört ja derjenige ist, der schläft.

Oder gibt es hierfür eine bessere Möglichkeit oder ein go-around?


Vielen Dank für eure Mühen und Antworten!
Mit freundlichen Grüßen
Genius
 
1) TCP oder UDP (STREAM / DGRAM)?
Bei UDP ist nicht wirklich garantiert, wie und ob die Daten ankommen,
dafür ist es etwas schneller als TCP-
Bei TCP kann/darf sowas nicht passieren, da muss der Fehler wo anders sein.

Wie sind den die Rückgabewerte?
Vllt. ist ja ein Fehler aufgetreten?
Returnwert unter 0 ist Fehler, genau 0 ist keine Verbindung.
Sonst die Byteanzahl., über 0.

Ein anderes mögliches Problem: send/recv müssen sich nicht an die Länge 4 halten.
Sie sind nur "verpflichtet", min. 1 und max. 4 Bytes zu verarbeiten.
send kann also zB. 4 Byte senden, aber recv nur 1 empfangen.
Um dann die restlichen 3 zu bekommen muss man recv öfter aufrufen,
bis man insgesamt 4 Byte hat.

Ca. so (auch gleich mit Fehlerprüfung):
C++:
int r, bytes, i;
...
bytes = 4; //Genau 4 Bytes empfangen
i = 0;
while(i < bytes)
{
    r = recv(socket, &variable[i], bytes - i, 0);
    if(r > 0)
        i += r;
    else if(r < 0)
        printf("Fehler %d\n", r);
    else printf("Keine Verbindung");
}
Für send ziemlich gleich, dafür muss es aber
eine char-Array-Variable sein (kein fixes Literal wie "123")


2) Kommt auf die Speichermenge an.

Wenn jeder Thread zB. bis zu 100MB brauchen kann,
besser erst bei Bedarf reservieren.

Bei normaleren Mengen würde ich gleich von Anfang an.


3) Du willst also praktisch ein sleep,
das aber bei Clientaktivität unterbrochen werden kann.

a) könnte recv das selbst.
Solange kein Byte vom Client kommt, wird sehr resourcenschonend gewartet.
Problem: Wenn der Threads mit anderen kommunizieren muss
(wenns auch nur die Beenden-Meldung ist etc.)

b) Die Funktion select
Man gibt einen (oder mehrere) Sockets,
dann wird gewartet, bis er was geschickt bekommt.
Vorteil zu recv selbst: Es gibt ein Timeout.

In einer Schleife immer select, das auch bei Nicht-Empfang naxh xv Millisekunden
fertig ist, dann die anderen Threadaufgaben, dann wieder select...

Anwendungsbeispiel hier: http://www.c-worker.ch/tuts/select.php#server

Gruß
 
Schonmal vielen Dank!

Ich arbeite mit TCP/STREAM. Bisher kamen die Daten immer wunderbar an, ich wollte es nur theoretisch wissen, ob es zu 0/1 Fehlern kommen kann. Wäre nämlich ziemlich fatal, wenn Cleint und Server verschiedene Datensätze besitzen!

Danke für die Schleife, werde das in meine Funktion einbauen!

Freue mich auf den Rest =)!

Mit freundlichen Grüßen
Genius
 
Rest ist jetzt oben.

Also, bei TCP kommen die Daten unverändert an.
Entweder liegts am eigenwilligen Mengenverhalten der Funktionen,
oder am restlichen Code.

Kannst ja mit zB. Wireshark überprüfen, was da übertragen wird.
 
Ich habe ein weiteres Problem ... bzw. ich stehe gerade irgendwie auf dem Schlauch!

Ich habe (ganz grob) folgenden Aufbau:

Code:
int y = 0;

pthread_function() {
	accept();
	y = 0;
}

main () {
	bind();
	listen();
	while(1) {
		if(y == 0) {
			y = 1;
			pthread_create()
		}
	}
}
Ich hoffe ich habe nichts vergessen, was zum verstehen meines Problems erheblich ist.

Das Programm startet -> socket wird gebunden und lauscht; y wird auf 1 gestellt. Wenn nun eine Client-Anfrage kommt, wird sie akzeptiert.

Mein Problem ist, dass die while(1) – Schleife während keine weiter Anfrage kommt völlig unnötig läuft und läuft und läuft … und schön brav mit nichts und wieder nichts meinen Prozessor auslastet. Am liebsten würde ich sie „blocken“ bis y wieder 0 ist ...

Ist mein Problem verständlich? Wie mache ich das?

Sieht mir nach einem sehr dummen Denkfehler aus :-D. Danke für eure Hilfe!

Mit freundlichen Grüßen
Genius
 
In der pthread_function wird also nicht nur akzeptiert,
sondern alles bis zum Schließen gemacht,
und die Schleife geht sinnlos.

Mach doch etwas wie
C++:
if(besetzt)
    sleep(1); //1 Millisekunde
in die Schleife.
Kein wirkliches Anhalten, aber die Prozessorlast ist weg.

Könnt nur eventuell Probleme machen, wenn sehr viele Verbindungen da sind.
(Aber diese 1-Client-Methode macht dann die größeren Probleme).
 
Ein sleep ist mir zu unsauber - auch nicht Sinn und Zweck der Sache - gibt sonst u.U. wie Sie schon richtig gesagt haben einen mega Stau ...

Aber diese 1-Client-Methode macht dann die größeren Probleme

Es ist keine 1-Client-Methode, der Thread macht seine Arbeit erst, nachdem y wieder auf 0 gestellt ist.

Trotzdem schonmal Danke!

Mit freundlichen Grüßen
Genius
 
Hallo,

ein Sleep finde ich nicht unsauber. Du musst dir immer überlegen, dass ein Prozessor eh niemals richtig angehalten werden kann. Dafür gibt es den Leerlaufprozess, der auch nichts anderes macht als immer wieder 1/2 zu rechnen o.ä.. Ein Sleep ist ansich sogar sehr schön: Er sagt dem Prozessor, dass er erstmal keine Rechenzeit mehr braucht und stellt diese dann dem Prozessor wieder zur Verfügung.
Als Alternative könntest du das ganze auch mit WaitForSingleObject() lösen. Eventuell auch WaitForMultipleObjects() [Ich habe jetzt dein Problem nicht im Detail angeschaut].

Im übrigen: Integers sind meines Wissens nach threadsafe. Allerdings solltest du dir im generellen immer überlegen, ob du von mehreren Seite ungeschützt auf eine Variable zugreifen solltest...

Die Frage wäre auch, wieviele gleichzeitige Verbindungen du für dein Programm erwartest, sodass ein Sleep von 1ms zu lange dauern würde?

Gruß,
kickerxy
 
Im übrigen: Integers sind meines Wissens nach threadsafe. Allerdings solltest du dir im generellen immer überlegen, ob du von mehreren Seite ungeschützt auf eine Variable zugreifen solltest...
Da kann man sich nicht verlassen.

Die Frage wäre auch, wieviele gleichzeitige Verbindungen du für dein Programm erwartest, sodass ein Sleep von 1ms zu lange dauern würde?
Genau.
Weiterer Punkt: Für so viele Verbindungen je einen Thread bereitstellen
ist auch nicht gerade unbelastend.
Ein Thread pro 64-Socket-Block ist eventuell besser...
 
Vielen Dank, das hat mir schon mal sehr weitergeholfen!

Im übrigen: Integers sind meines Wissens nach threadsafe. Allerdings solltest du dir im generellen immer überlegen, ob du von mehreren Seite ungeschützt auf eine Variable zugreifen solltest...

Ja, weiß ich - in diesem Fall (y) ist es unmöglich, dass zwei threads gleichzeitig darauf zugreifen. Trotzdem vielen Dank für den hinweis =)!

Weiterer Punkt: Für so viele Verbindungen je einen Thread bereitstellen
ist auch nicht gerade unbelastend.
Ein Thread pro 64-Socket-Block ist eventuell besser...

Ich hatte eigentlich vor die threads mit pthread_attr_setstacksize den stack "verbrauch" auf ein minimum herunter zu brechen, zudem die threads die nichts zu tun haben brav schlafen lassen ...

Wenn es zu viele Anfragen werden, muss dann eben u.U. ein vielkerniger Prozessor her um alle threads zu verarbeiten ...

Vielen Dank!

Mit freundlichen Grüßen
Genius
 
Zurück