Seite 1 von 1

Client/Server-Prinzip

Verfasst: 17. Juli 2008 06:15
von chrislo1976
Hallo zusammen!

Ich hätte heute eine Frage zum Thema Client/Server-Applikation und wie man am besten/einfachsten komplexere Datenstrukturen überträgt. Ist eigentlich nicht direkt QT-spezifisch, da ich es aber mit QT umsetzen möchte finde ich es hier schon passend.

Kurzer Hintergrund:
Ich habe schon mehrere Programme (mehr oder weniger Clients) geschrieben die direkt auf eine Datenbank zugreifen, dabei werden diese Programme von mehreren Personen verwendet. Jetzt steht wieder ein neues Programm an, wieder mit selben Prinzip. Mir hat das aber schon länger nicht mehr gefallen dass diese Programme direkt auf die Datenbank gehen, ich hätte da gerne ein "Kontrollorgan" dazwischen, eine Server-Applikation.
Ich habe mit Client/Server-Programmierung nicht wirklich Erfahrung und mehr als einen String über TCP von Programm A nach B zu schicken hab ich auch noch nicht gemacht.

Das einfache am direkten Verbinden mit einer DB ist halt dass ich direkt die SQL-Objekte von Qt verwenden kann und mir um viele Dinge keine Sorgen machen muss. Wie stellt man das nun am besten mit einem dazwischenliegenden Server an? Dem Server dabei mitzuteilen was der Client aus der DB haben möchte sollte ja noch kein Problem sein, aber was ist mit den Ergebnissen die der Server an den Client senden muss?
Gibts da vielleicht fertige Mechanismen um z.B. ein QSqlQuery-Objekt von einem Programm in das andere zu übertragen? Oder müsste ich da praktisch ein eigenes Protokoll entwickeln in dem die einzelnen Daten der DB übertragen werden?

Ihr seht schon, das sind keine speziellen Fragen, sondern eher konzeptioneller Art. Momentan wüsste ich einfach gar nicht wie ich das angehen soll.

Hat jemand von euch schon sowas ähnliches realisiert? Oder kann mir sonst jemand irgendwelche Tipps geben. Es muss dabei wirklich nicht ins Detail gehen, sondern nur grob die Richtung zeigen.

Wie ist es denn eigentlich generell mit Client/Server-Verbindungen. Kann man das mit moderaten Aufwand hinbekommen, oder ist das relativ schwer umzusetzen. Wie gesagt, ich habe da nicht so viel Erfahrung, und möchte mich da in nichts verrennen wo der Aufwand in keiner Relation zum Nutzen ist.

Ich hoffe ich konnte mein Anliegen einigermaßen erleuchten und hoffe ihr könnt mir da ein wenig helfen.

Danke schon mal im Voraus!

Gruß,
Christian

Verfasst: 17. Juli 2008 09:06
von chrootdev
Hi,

das ist wirklich eher konzeptioneller art, aber ich bin auch gerade an sowas dran und komm nicht weiter!

Das problem das du hast, hab ich mit XML gelöst! Bei mir ist das momentan noch sehr oberflächlich. Ich sende vom client eine anfrage per xml an den server, dieser parst das und verpackt die antwort (zb. von einer SELECT abfrage) wiederum als XML und sendet es and den client zurück!

Bei SELECT wird eben eine entsprechende struktur zurückgeschickt, bei INSER, DELETE und UPDATE einfach nur "error" oder "success".

Aber was ich noch nicht ganz durchblicke, wie man das mit der datenbank handhabt. Mein ziel ist es , einen server mit einer config datei zu erstellen, und beim starten gibt man diese config datei an. Darin sollten neben startparametern auch die zugangsdaten für die datenbank gespeichert werden.

Jetzt weiß ich eben nicht soll ich die datei verschlüsseln? Dann müsste man bei jedem start vom server das passwort eingeben. Aber andererseits wird der server ja für linux entwickelt, und da kann man das verzeichnis durch rechtevergabe auch schützen. Ab hier fehlt mir der plan.

Verfasst: 17. Juli 2008 12:19
von upsala
Das mit dem XML-Format wäre auch mein Vorschlag gewesen.

Das mit dem Verschlüsseln, der Datei macht keinen Sinn, den du mußt es ja wieder entschlüsseln, also wieder ein Passwort...

Bei INSERT, UPDATE und DELETE könnte man noch die Anzahl der betroffenen Datensätze zurückgeben, falls es irgendwann mal interessiert.

Verfasst: 17. Juli 2008 12:39
von chrootdev
Oder man kann dann bei UPDATE und INSERT auch das ergebnis eines darauffolgenden SELECT zurücksenden, so als zusammenfassung oder so!

@upsala: Also einfach im klartext die config datei und das rechtesystem von linux verwenden oder wie?

Verfasst: 17. Juli 2008 15:52
von upsala
Ja, entweder das, oder jedes mal beim starten das Passwort angeben

Verfasst: 18. Juli 2008 11:55
von RHBaum
Es gibt dutzende von Möglichkeiten .... und jedes hat so seine vor und nachteile ...

du brauchst quasi "nen protokoll" fuer deine datenuebertragung.
XML waere nur der protokolltyp, den inhalt musst ja noch selber spezifizieren.

XML geht halt gut zu parsen, und das Protokoll kann damit sehr leicht fehlertolerant und flexibel sein.
Auf der anderen seite steht die performance ....

und es bietet sich an, wenn man sich den server entwickeln sparen will :-) einfach nen apache aufsetzen den client die anfragen als http gets formulieren lassen, und serverseitig das xml generieren zu lassen.
Ausbau zu SSL waer inklusive ...

Spielt der datendurchsatz ne Rolle, wuerd ich nen binaeres protokoll aufbauen und streamen. Das ist aber konzepttechnisch / entwicklungstechnisch nen ziemlicher brocken, und alles andere als flexibel. Wirklich nur gangbar wenn die datenstrukturen recht simpel sind ...

weitere Alternativen um ein protokoll zu abstrahieren und mehr auf eine prozedurale Schiene zu bringen sind die RPC Abkoemmlinge / Middleware technologien, ala DCOM / Corba ....

Was fuer dich in frage kommt, musst selber entscheiden ...
Ich wuerds erst mal mit XML (am einfachsten implementieren)
Also einfach im klartext die config datei und das rechtesystem von linux verwenden oder wie?
Wenn man paranoid ist, kann mans ja noch asynchron verschluesseln :-)
Also z.b. dem server nen modus (per commandline options) verpassen, wo er die DB anlegt, die Strukturen (tabellen) erzeugt etc .... und das mituebergebene passwort erstmal gehasht (crypt) wird und der hash als password in der DB eigetragen und gleichzeitig deine config datei erzeugt wird, wo der hash dann als passwort zum einloggen mit abgelegt wird.
Das schuetzt aber nur das passwort selber (falls man sich nur eines merken kann und das wiederverwenden will), macht da also ned zuviel sinn, sieht aber dann schoen linux konform aus (siehe /etc/shadow oder /etc passwd).

Ciao ...

Verfasst: 22. Juli 2008 18:25
von chrislo1976
Hallo!

Also die Idee mit XML gefällt mir sehr gut! Hät ich eigentlich selbst drauf kommen können, da wir meist für den Import und Export von Daten XML verwenden; naja, manchmal sieht man den Wald vor lauter Bäumen nicht...

Ich habe diese Möglichkeit inzwischen auch bei uns in der Firma vorgetragen. Leider wurde das Server-/Client-Prinzip aus verschiedenen Gründen auf Eis gelegt. :?
Nichts desto trotz werde ich privat weiter daran arbeiten, einfach um damit Erfahrungen zu sammeln. Ich denke dass früher oder später nichts daran vorbeigeht.

Das nächste Problem taucht dann schon auf der Serverseite auf! Anfangs dachte ich ganz einfach "für jede Verbindung einen extra Thread"! Allerdings ist das, wie ich gelesen habe, nicht wirklich praktikabel; d.h. eigentlich müsste dann sowas wie ein Thread-Pool her. Und damit bin ich dann soweit dass so ein Server nicht so leicht zu realisieren ist wie ich erhoffte.

Wie gesagt, ich bleibe diesbezüglich dran. Vielleicht hat ja der eine oder andere noch ein paar Infos oder sonstige Hilfestellungen; würd mich jedenfalls darüber freuen.

Gruß,
Christian

Verfasst: 22. Juli 2008 18:44
von upsala
Threads? Brauchst du nicht, hier ein Auszug aus einem kleinen Server-Test, an dem ich die letzten Tage etwas getestet hatte:

Code: Alles auswählen

Server::Server(QObject *parent)
  : QObject(parent)
{
  m_server=new QTcpServer(this);
  m_server->listen(QHostAddress::Any, 15000);
  connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
}

void Server::newConnection()
{
  QTcpSocket *socket=m_server->nextPendingConnection();
  if (socket) {
    Parser *parser=new Parser(socket, this);
  }			
}

Verfasst: 23. Juli 2008 05:41
von chrislo1976
Moin!

Gut, wenn es darum geht die eingehenden Anfragen von den Clients aufzunehmen würde es sicherlich ohne Threads gehen. Ich denke dabei aber mehr an die Arbeit die der Server verrichten muss um z.B. die gewünschten Daten aus einer Datenbank zu holen.
Erfahrungsgemäß kann es da schon ein paar Sekunden dauern bis die Daten zurückkommen (teilweise wegen großen Datenmengen oder komplexen Abfragen). Wenn jetzt sagen wir mal 10 Clients verbunden sind und jeder stellt so eine Abfrage, dann kanns doch passieren das der "letzte" Client ziemlich lange warten muss bis er an der Reihe ist!?

Deswegen hätte ich (zumindest) die Datenbankabfragerei in extra Threads gepackt. Dann wiederum kann ich aber die Qt-SQL-Objekte nicht benutzen, die dürfen ja nur in dem Thread benutzt werden in dem sie erzeugt wurden. Aber wenn sich die Clients nicht mehr direkt mit der DB verbinden, könnte man eigentlich vom Server aus mehrere Verbindungen zur DB aufmachen...

@upsala:
Machst du in deinem Programm die Verbindung nach jeder Abfrage eigentlich wieder zu, oder bleibt die solange offen bis sich der Client komplett vom Server trennt? Wie macht man das üblicherweise?

Gruß,
Christian

Verfasst: 23. Juli 2008 09:08
von upsala
Das kommt darauf an, was man vorhat. Wenn man sich die üblichen Protokolle im Netz ansieht, ist es doch so, daß HTTP gleich nach Antwort wieder geschlossen wird, IMAP oder SSH aber offen bleiben bis sich der Client abmeldet.

Und meines Wissens kann man in verschiedenen Threads schon mehrere Datenbank-Verbindungen aufbauen. Man darf halt nur nicht die selbe Verbindung in mehreren Threads verwenden.

Verfasst: 23. Juli 2008 09:43
von chrootdev
Also könnte ich bei 10 clients demnach 10 threads laufen lassen und darin 10 datenbank interaktionen durchführen? Cool...

@chrislo1976: Ich glaube wir beide haben das selbe vor! Einen server der für jeden client per thread seine arbeit erledigt.

Verfasst: 23. Juli 2008 12:25
von RHBaum
Ich glaube wir beide haben das selbe vor! Einen server der für jeden client per thread seine arbeit erledigt.
kein wunder, weils ja quasi standard ist ....
nen iterativen server, also wo mit select und nur einen thread/process gearbeitet wird, macht kaum einer ...

unterschiede gibts nur ob multithreading, multiprocessing (fork) oder ne combi aus beiden, mit oder ohne pools gearbeitet wird ...

ob verbindungsorientiertes oder verbindungsloses protokoll wuerd ich vom anwendungsfall abhaengig machen ...
bei DB nutzung mit authentifizierung etc ist fast immer nen protokoll besser geeignet, was die verbindung haelt, erspart viel aerger oder performance probleme ....
Wenn man mal ueber http(s) was umfangreichers programmiert hat, selbst mit serversripten etc, weill was man fuer aerger mit den datenbankverbindungen bekommen kann (sessionManagment) ...

Ciao ...