Paralleler TCP-Server mit select()

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Paralleler TCP-Server mit select()

Beitrag von Columbus » 22.06.2006 19:29:06

Hallo zusammen, hallo nach Wien 8)

Bei mir gehts weiter mit der Netzwerkprogrammierung. Jetzt habe ich einen TCP-Server erzeugt, der von mehreren Clients angesprochen werden kann. Zu sehen ist er hier:
http://nopaste.debianforum.de/3493

Der Server funktioniert, er kann mit mehreren Clients verbindung aufnehmen und teilt mit wann welcher Client sich anmeldet und wann wieder abmeldet.
Meine Frage ist mehr prinzipieller Natur. Im Moment ist der Server ein "gedächtnisloser Prozess". Also jede Anfrage ist genau wie die Andere. Ich möchte ihn dahin bringen, daß er sich merkt, was dieser oder jener Client beim letzten Mal gemacht hat. Also sagen wir die Clients schicken zunächst eine Zahl, die die Länge des Strings ankündigt, der bei der nächsten Sendung zu empfangenden ist. Also erst schickt er eine 7 und dann "**END**". (um beim letzten Beispiel zu bleiben). Ist das ein guter Ansatz? Oder gibt es hier einen Königsweg, wie man solche Nachrichten zwischenspeichert?

Und überhaupt, wie sauber ist der Code? Wo kann man was verbessern?
Ich gebe zu ich habe im Netz einiges abgekuckt :)

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 22.06.2006 21:00:58

Hallo Columbus

habe gleich einmal einen Streßtest mit deinem Server duchgeführt, den dieser auch ohne Absturz überstanden hat. Dann ist mir aber diese sonderbare Ausgabe aufgefallen:

Code: Alles auswählen

warte jetzt auf Clients
Die Client-Nummer: 0 ist 4
Die Client-Nummer: 1 ist 5
Die Client-Nummer: 2 ist 6
Die Client-Nummer: 3 ist 7
Die Client-Nummer: 4 ist 8
Die Client-Nummer: 5 ist 9
Die Client-Nummer: 6 ist 10
Die Client-Nummer: 7 ist 11
Die Client-Nummer: 8 ist 12
Die Client-Nummer: 9 ist 13
Die Client-Nummer: 10 ist 8
Server ist besetzt
Hier hast du einen "buffer overflow", die Client-Nummer für 10 dürftest du gar nicht mehr auslesen, wenn du mit 0 zum Zählen beginnst

Hier schreibst du sogar ungewollt über den Speicherbereich hinaus:

Code: Alles auswählen

#define MAX_CLIENTS  10
...
  int client_nummer[MAX_CLIENTS];

  /*Alle Clients werden zurückgesetzt                                                                                */
  for ( zaehler = 0; zaehler <= MAX_CLIENTS; zaehler++ )
  {
    client_nummer[zaehler] = -1;
  }
Hier hast du die Schleife richtig:

Code: Alles auswählen

  /* Ermittele jetzt den groessten Descriptor                                                           */
  for ( zaehler = 0; zaehler < MAX_CLIENTS; zaehler++ )
Columbus hat geschrieben: Also jede Anfrage ist genau wie die Andere. Ich möchte ihn dahin bringen, daß er sich merkt, was dieser oder jener Client beim letzten Mal gemacht hat
Hast du schon eine Idee wie sich der Client als jener Client vom letzte Mal zu erkennen gibt ?


Gruß
gms

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 23.06.2006 12:18:59

Na ich denke doch über den Socket, bzw den Socket-Descriptor, der von Select zurückkommt. Ich müsste Abfragen, ob dieser Socket schon vergeben war, oder neu ist.

Also als Beispiel, Client Nr 0 meldet sich mit dem Socket 0 an. Das was er schreibt, wird in eine Struktur (mit Malloc) geschrieben. Diese Struktur könnte ich in eine verkettete Liste eintragen oder ein Array (aus Zeigern) daraus erzeugen ( ich weiß ja es kann nur 10 davon geben ).

Wenn der Client wieder da ist, (Frage) kommt er wieder mit dem gleichen Socket?
Ich denke schon, nach allem was ich probiert habe, konnte der Server die Clients wieder erkennen. Dann brauche ich einfach nur nachschauen, ob schon eine Struktur vorhanden ist. Wenn ja lese ich aus dieser Struktur das was der Client beim letzten mal übertragen hat, wenn nein wird eine neue Struktur angelegt.

Also das versuche ich jetzt!

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 23.06.2006 19:10:02

Columbus hat geschrieben:Also jede Anfrage ist genau wie die Andere. Ich möchte ihn dahin bringen, daß er sich merkt, was dieser oder jener Client beim letzten Mal gemacht hat
das habe ich dahingehend interpretiert, daß die Verbindung zwischendurch geschlossen wird
Columbus hat geschrieben:Na ich denke doch über den Socket, bzw den Socket-Descriptor, der von Select zurückkommt.
ganz kann ich mir das dann nicht vorstellen:

sagen wir der Client1 baut die Verbindung auf und bekommt den Socket n
dann baut Client2 eine Verbindung auf und bekommt den Socket n+1
beide Clients schließen die Verbindung
Client2 baut neuerlich eine Verbindung auf und bekommt dann den Socket n
Client1 baut neuerlich eine Verbindung auf und bekommt dann den Socket n+1


Gruß
gms

Benutzeravatar
Columbus
Beiträge: 1051
Registriert: 30.04.2002 15:25:02
Wohnort: Mainz
Kontaktdaten:

Beitrag von Columbus » 24.06.2006 12:23:16

Nein, die Clients schliessen nicht die Verbindung, das war ein Mißverständnis. Ich war mir nur nicht sicher ob das wirklich so ist, daß ein Client so lange er angemeldet ist auch seinem Descriptor "treu" bleibt. Aber so viel ich jetzt mitbekommen habe ist das wohl so und ist auch notwendig.

Gruss Christian
Die größten Kritiker der Elche,
waren früher selber welche.

F.W. Bernstein

Antworten