PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Server, der auf Empfang wartet


Marscel
2006-01-18, 16:56:06
Ich bin gerade dabei, meine C++ Kenntnisse an einem winzigen Server-Programm (bisweilen Windows mit winsock.h) zu testen: Das Ding soll einen Clienten verbinden lassen und solange wie der Client verbunden ist, Rohdaten annehmen lassen, diese weiterverarbeiten und dann eine Bestätigung schicken an den Clienten, dass alles hingehauen hat.

do
{
if(client = accept(server, (struct sockaddr*)&from, &from_len))
{
// char * messages[] = { "Bla", ... };
send(client, messages[0], strlen(messages[0]), 0);
}
} while(1);

Das funktioniert auch alles gut, der Server nimmt mehrere Verbindungen an. Meine Fragen:

1.) Wie kann man den Server dazu bestimmen, auch ähnlich auf Datenempfang zu reagieren?

Wenn ich das in die Schleife darunter setze, funktioniert das nicht wie gewünscht, sondern nur exakt einmal (obwohl es in einer endlosen do-Schleife ist):

if(recv(client, temp, sizeof(temp), MSG_PEEK))
{
send(client, messages[1], strlen(messages[1]), 0);
}

2.) Es wird immer dasselbe struct vom Typ SOCKET benutzt, nämlich 'client', das wird doch immer wieder überschrieben (da Rückgabewert von accept), wenn ein neuer Client verbindet, oder?
Geht das überhaupt, dass mehrere Clienten auf einmal verbunden sind? Oder sollte man die Clienten in einem Container speichern oder ist das gar nicht nötig?

3.) Wie kann man prüfen, ob der Client die Verbindung geschlossen hat (Terminierungssymbol oder so...) ?

4.) Wie kann man identifizieren, von welchem Clienten die gesendeten Daten stammen? Den Socket weiß ich ja, 'client', aber gibt/schreibt recv() irgendwas an Infos, z.B. dessen Addresse?

Damals bei PureBasic (nicht lachen), gabs einfach eine Funktion, die ständig den Socket auf Aktivitäten überwachte und per case-Zweig handelte, z.B. Client sendet, Client schließt Verbindung etc.

Trap
2006-01-18, 17:23:56
http://bulk.fefe.de/scalable-networking.pdf

Hat am Anfang ein paar einfache Beispielserver. fork() dürfte allerdings unter Windows Probleme machen.

Achso: http://tangentsoft.net/wskfaq/ ist auch ganz nett

Marscel
2006-01-18, 18:10:14
Achso: http://tangentsoft.net/wskfaq/ ist auch ganz nett

Das sieht sehr interessant aus, werde ich mir anschauen, danke.

muhkuh_rs
2006-01-18, 18:35:18
Was genau soll denn passieren? Der Server soll auf gesendete Daten der clients damit reagieren, dass er die Nachricht sendet? Dann musst du die Lister der verbundenen clients doch irgendwo speichern und entweder die einzelnen Verbindungen auf neue Daten pollen, pro client einen Thread aufmachen, mit Callbacks arbeiten oder ... da war noch was aber das hab ich vergessen.

Trap
2006-01-18, 19:04:29
Es gibt grundsätzlich 2 Modelle für Server:
-event basierend
-multiprocessing basierend

Bei multiprocessing Servern bedient jeder Prozess/Thread/Ausführungseinheit einen Client und alle Socket-Operationen blockieren bis sie abgeschlossen sind.

Bei event basierenden Servern bedient ein Prozess alle Clients und hält für jeden Client eine Statemachine bereit mit der er ermittelt was er als nächstes machen muss. Alle Eingaben von Client werden in einer zentralen Eventloop nacheinander angesehen, die zugehörige Statemachine ermittelt und die nächste Operation wird initiiert. Dazu benutzt man nonblocking Sockets und select()/poll/epoll/kqueue/completion ports oder wie es auch immer auf dem OS heißt.

Marscel
2006-01-18, 19:17:07
Was genau soll denn passieren? Der Server soll auf gesendete Daten der clients damit reagieren, dass er die Nachricht sendet?

Kurz gesagt: Der Server soll von x-beliebig vielen Clienten Daten empfangen, unter Windows eben Kommandozeileneingaben (so kann ich bei PC1 über ein PUTTY oder Telnet z.B. 'net start mysql' eingeben, um einen Datenbankdienst zu aktivieren). Wenn dieses Kommando ausgeführt wurde, soll der Server einfach eine Botschaft "Ausgeführt: net start mysql" oder so zurückschicken.

Wichtig ist, dass ich nicht für jede Operation neu verbinden möchte, weil ich nur ein oder zwei recv() im Ablauf des Servers habe, bevor er die Verbindung wieder schließt.

Dann musst du die Lister der verbundenen clients doch irgendwo speichern und entweder die einzelnen Verbindungen auf neue Daten pollen, pro client einen Thread aufmachen, mit Callbacks arbeiten oder ... da war noch was aber das hab ich vergessen.

Das war ja auch eine meiner Fragen, wie man das am besten macht.

Coda
2006-01-18, 21:49:39
-