Entwickler-Ecke
Internet / Netzwerk - Konzeptfrage - Internet-Chat als Freeware, wie?
chrisdrury - Mi 20.02.08 15:21
Titel: Konzeptfrage - Internet-Chat als Freeware, wie?
Hallo Leute,
da ich meinen auf der Basis der Indy TCP-Komponenten erstellten Internet-Chat als Freeware veröffentlichen möchte, habe ich da eine Frage zum Konzept: :gruebel:
Der Chat beruht auf folgendem Prinzip:
Der Server nutzt die IP des PCs, auf dem er läuft und die Clients loggen sich bei dieser IP ein.
So weit, so einfach. Nun stellt sich mir aber folgendes Problem:
Wie erfahren die Clients die notwendige IP?
Meine Idee: Ich richte eine globale Website ein, wo sich jeder Server mit Angabe der IP anmelden kann.
So müssen die Clients nur noch auf dieser Seite die entsprechende IP suchen.
Wie kann man so etwas am besten machen? Eventuell mit einer Datenbank? Wie sicher ist so was?
Hat jemand vielleicht noch eine andere Idee?
Bin für jedes Posting dankbar! :wave:
jaenicke - Mi 20.02.08 15:49
Eine Datenbank ist sicher eine gute Idee, du solltest nur vermeiden, das Passwort direkt in deinem Programm anzugeben. Am sinnvollsten ist es vermutlich, wenn du eine PHP-Datei ansprichst, die die Eintragung in die Datenbank (und ggf. Löschung alter Beiträge) übernimmt. Diese kann nämlich dafür sorgen, dass die Einträge vorher geprüft werden.
opfer.der.genauigkeit - Mi 20.02.08 16:08
Ich würde vorschlagen, dass die Clients im Code bereits wissen wohin sie sich verbinden sollen
oder du lagerst das in eine Konfigurationsdatei aus... wie du magst.
Wenn der Server eine fixe IP hat ist das nicht so das Problem, wenn du eine dynamische
IP hast, dann kannst du über die URI die IP herausbekommen.
Aber es müsste auch so gehen:
example.com
Den Namen musst du dann IMHO nicht selber auflösen.
Hab ich aber noch nie getestet.
jaenicke - Mi 20.02.08 16:15
Das hast du falsch verstanden ;-). Es geht darum, eine Vermittlungsstelle aufzubauen, die eine Liste der Server hält. Die Server sind vorher nicht bekannt und können von den Usern vermutlich selbst einfach aufgemacht werden.
Dass dazu noch Tunneling bzw. Portforwarding, etc. als mögliches Problem kommt, ist allerdings auch klar, aber ich denke mal, das ist
chrisdrury genauso klar.
opfer.der.genauigkeit - Mi 20.02.08 16:30
Na dann entweder, wie vorgeschlagen über eine Serverseite oder beim Start des Clients
vom Hauptserver eine Liste aller verfügbaren Server anzeigen.
Es ist dann Sache der neuen Server sich vorher in diese Liste einzutragen, was aber
der gleiche Aufwand für neue Server ist.
Mit einer Liste, die beim Start dem User im Client angezeigt wird, bleibt zumindest dem User
erspart, dass er extra auf einen Link gehen muss.
Die Liste kann man dann ja nach belieben bequem machen und soetwas wie Favoriten und History hinzufügen.
Naja und optional eben immer das Hinzufügen beliebiger Server, die nicht in die List wollten...
In allen Fällen muss es aber eine Datenbank geben, ich empfehle PostgreSQL.
Für den Client empfiehlt sich eine Configdatei, die auch vom User sinnvoll editiert werden kann.
chrisdrury - Do 21.02.08 10:07
So, um das Ganze noch mal etwas detaillierter darzustellen:
Der Chat läuft seit einiger Zeit quasi in einer Art Test, zwar übers Internet, aber nur mit einigen ausgesuchten Clients.
Der Server wird dabei immer auf meinem PC gestartet und teilt die IP meines Computers mittels FTP einer bestimmten Website mit.
Die Clients suchen beim Einloggen automatisch nach einer bestimmten Stelle im HTML-Quelltext dieser Seite, um festzustellen, ob der Server online ist oder nicht. Ist er online, wird die IP aus eben diesem Quelltext ausgelesen und der Client loggt sich ein.
Wird der Server abgemeldet, läuft das Ganze genauso.
Nun zur praktischen Erweiterung des Chats:
Ich habe bei meinem Webspace-Provider einen FTP-Account eingerichtet, der nur den Zugang zu einem ganz bestimmten Verzeichnis zulässt. In diesem Verzeichnis soll dann der gesamte "Verkehr" des Chats verwaltet werden, also die Darstellung der aktiven Server, vielleicht nach dem Muster Angabe der IP, Name eines Chatroomes und einer Kategorie wie z.B Programmierung oder Sport.
Könnte man so etwas mit einer PHP-Datei machen? Vielleicht eine einfache Liste per HTML z. B. in einem <DIV>-Container verwalten? :gruebel:
Oder mit einer Datenbank? Auf meinem Webspace läuft eine MySQL-Datenbank, da könnte ich ja eine entsprechende Tabelle einrichten. Aber ist das nicht etwas aufwändig?
Und wie sieht es da mit der Sicherheit aus, schließlich muss jeder Server ja auch die Zugangsdaten der Datenbank kennen... :?:
jaenicke - Do 21.02.08 12:31
chrisdrury hat folgendes geschrieben: |
| Könnte man so etwas mit einer PHP-Datei machen? Vielleicht eine einfache Liste per HTML z. B. in einem <DIV>-Container verwalten? :gruebel: |
Ja, wobei ja noch nichtmal HTML-Code dazwischen sein muss, da ja nur dein Programm das auslesen und anzeigen soll.
chrisdrury hat folgendes geschrieben: |
Oder mit einer Datenbank? Auf meinem Webspace läuft eine MySQL-Datenbank, da könnte ich ja eine entsprechende Tabelle einrichten. Aber ist das nicht etwas aufwändig?
Und wie sieht es da mit der Sicherheit aus, schließlich muss jeder Server ja auch die Zugangsdaten der Datenbank kennen... :?: |
Nein, eben das ist nicht nötig...
jaenicke hat folgendes geschrieben: |
| Eine Datenbank ist sicher eine gute Idee, du solltest nur vermeiden, das Passwort direkt in deinem Programm anzugeben. Am sinnvollsten ist es vermutlich, wenn du eine PHP-Datei ansprichst, die die Eintragung in die Datenbank (und ggf. Löschung alter Beiträge) übernimmt. Diese kann nämlich dafür sorgen, dass die Einträge vorher geprüft werden. |
Hier ist auch ein kleines Beispiel, der Dateiupload ist dabei nicht nötig und die Daten müssen statt in eine Datei eben in eine Datenbank:
http://www.delphipraxis.net/topic98281.html
chrisdrury - Fr 22.02.08 08:38
@ jaenicke: Danke für Deine Geduld, ich glaube jetzt habe ich es verstanden. :wink:
Also, ich werde es jetzt so machen:
Eine MySQL-Tabelle für die Daten der Server (IP-Nummer, Port und weitere Infos) ist auf meinem Webspace bereits eingerichtet.
Eine PHP-Datei mit den Zugangsdaten der Datenbank liegt dort ebenfalls bereit.
Die gesamte Kommunikation zwischen den Servern bzw. Clients und dieser Datenbank wird über PHP-Scripte gesteuert.
Dabei verwende ich die Komponente IdHttp von Indy, um die auf den lokalen Rechnern zusmmmengestellten Scripte an die Datenbank zu senden.
Im einzelnen:
Der Server sendet beim Anmelden einen SQL-INSERT-Befehl über IdHttp, damit er in die Datenbank aufgenommen wird.
Der Client sendet ein Script mit einem SELECT-Befehl zur Anzeige der aktiven Server, zum Einloggen wird dann die entsprechende IP übernommen.
Beim Abmelden sendet der Server einen DELETE-Befehl, um den Datensatz aus der Datenbank zu löschen.
Zur Anzeige der aktiven Server plane ich einmal eine PHP-Datei mit HTML-Befehlen zur Darstellung im Browser sowie ein Script mit reinem PHP, um möglichst nur die Daten aus der Datenbank an die Clients zu schicken.
Dabei plane ich, die Felder der Datenbank mit Kommas und die einzelnen Datensätze mit
z. B. <br> zu trennen, um sie eventuell in eine Stringlist laden zu können.
Wäre nett, wenn jemand mal checken könnte, ob ich irgendetwas vergessen habe oder ob es vielleicht einfacher gehen könnte... :lupe: :zwinker:
jaenicke - Mo 25.02.08 12:00
chrisdrury hat folgendes geschrieben: |
| Dabei verwende ich die Komponente IdHttp von Indy, um die auf den lokalen Rechnern zusmmmengestellten Scripte an die Datenbank zu senden. |
Ich war übers Wochenende im Urlaub, deshalb kommt erst jetzt eine Antwort.
Ja, ich weiß nicht, wie du das meinst. Richtig wäre, PHP-Skripte auf dem Server aufzurufen mit den entsprechenden Parametern. Ungünstig wäre es, die MySQL-Befehle zu schicken zur Ausführung, weil dann jemand sehr leicht falsche unterschieben könnte und mit dem Server Schindluder treiben könnte.
Beispiel:
http://server.de/entries.php?action=add&ip=127.0.0.1&port=222 wäre dann ein Aufruf des Skriptes wie ich es meinte zum Beispiel.
Es kann natürlich sein, dass du das auch so meintest, es hörte sich jetzt für mich allerdings nicht so an ;-).
chrisdrury - Mo 25.02.08 15:41
jaenicke hat folgendes geschrieben: |
Ja, ich weiß nicht, wie du das meinst. Richtig wäre, PHP-Skripte auf dem Server aufzurufen mit den entsprechenden Parametern. Ungünstig wäre es, die MySQL-Befehle zu schicken zur Ausführung, weil dann jemand sehr leicht falsche unterschieben könnte und mit dem Server Schindluder treiben könnte.
Beispiel: http://server.de/entries.php?action=add&ip=127.0.0.1&port=222 wäre dann ein Aufruf des Skriptes wie ich es meinte zum Beispiel.
Es kann natürlich sein, dass du das auch so meintest, es hörte sich jetzt für mich allerdings nicht so an ;-). |
Ich bin mir ehrlich gesagt auch noch nicht so sicher, wie ich das realisieren soll. :wink:
Bin nämlich nicht so der PHP-Experte... :oops:
Wenn ich nun folgendes PHP-Script nehmen würde, ginge das überhaupt mit IdHttp?
Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| <?php include("einlog.php"); include("funk.php"); $connect=@mysql_connect($dbHost, $dbUser, $dbPass) or die("F"); $sql = "insert into Chat (IP,Port,Name) VALUES ($IP, $Port, $Name)"; If ($res=send_sql($db,$sql)) {echo "OK";} ?>? |
jaenicke - Mo 25.02.08 20:08
Ja, klar geht das mit IdHttp, wobei du, wenn du einfach eine Adresse nimmst wie ich im Beispiel und diese mit IdHttpX.Get('http://...') abrufst, dann die Daten über $_GET im Skript verfügbar sind:
$_GET['ip']
(also statt $IP wie in deinem Quelltext).
Was ist send_sql? Die Funktion kenne ich gar nicht...
Ich benutze immer mysql_query und ggf. danach eine entsprechende Fehlerabfrage.
chrisdrury - Mo 25.02.08 21:11
jaenicke hat folgendes geschrieben: |
Was ist send_sql? Die Funktion kenne ich gar nicht...
Ich benutze immer mysql_query und ggf. danach eine entsprechende Fehlerabfrage. |
Ist fast genau dasselbe, eine selbst erstellte Funktion mit mysql_query. habe ich nur in die Datei funk.php ausgelagert.
chrisdrury - Di 26.02.08 07:59
Also müsste die entsprechende PHP-Datei so aussehen?
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| <?php include("einlog.php"); include("funk.php"); $IP=$_GET['IP']; $Port=$_GET['Port']; $Name=$_GET['Name']; $connect=@mysql_connect($dbHost, $dbUser, $dbPass) or die("F"); $sql = "insert into Chat (IP,Port,Name) VALUES ($IP, $Port, $Name)"; If ($res=send_sql($db,$sql)) {echo "OK";} ?> |
Dazu ein Ausschnitt aus der funk.php:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| ... function send_sql($db, $sql) { if (! $res=mysql_db_query($db, $sql)) { echo mysql_error(); exit; } return $res; } ... |
Xong - Di 26.02.08 09:42
chrisdrury hat folgendes geschrieben: |
| Also müsste die entsprechende PHP-Datei so aussehen? |
Nein! Ein deutliches Nein! =)
Quelltext
1: 2:
| $sql = "insert into Chat (IP,Port,Name) VALUES ($IP, $Port, $Name)"; |
Nehmen wir an, ich rufe deine Seite wie folgt auf:
http://example.org/index.php?Name=Blubb);GO+EXEC+cmdshell('format+c')+--
Daraus würde folgendes werden:
SQL-Anweisung
1: 2: 3: 4:
| insert into Chat (IP,Port,Name) VALUES (, , Blubb); GO EXEC cmdshell('format c') --)"; |
Du musst dich auf jeden Fall gegen
SQL-Injektionen [
http://de.php.net/manual/de/security.database.sql-injection.php] absichern.
Man kann sonst noch viel fiesere Dinge anstellen.
Also mindestens
mysql_real_escape_string() [
http://de.php.net/manual/de/function.mysql-real-escape-string.php] benutzen und die zwei Links durcharbeiten! ^^
LG,
Xong
chrisdrury - Di 26.02.08 10:47
Ok, danke, ich habe ja angemerkt, ich lerne noch PHP... :wink:
Also wäre das die Mindestanforderung?
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| <?php include("einlog.php"); include("funk.php"); $IP=$_GET['IP']; $Port=$_GET['Port']; $Name=$_GET['Name']; $connect=@mysql_connect($dbHost, $dbUser, $dbPass) or die("F"); $sql = sprintf("insert into Chat (IP,Port,Name) VALUES ($IP, $Port, $Name)", mysql_real_escape_string($IP), mysql_real_escape_string($Port), mysql_real_escape_string($Name)); If ($res=send_sql($db,$sql)) {echo "OK";} ?> |
jaenicke - Di 26.02.08 11:03
Also ich kenne sprintf jetzt nicht so genau, aber ich würde sagen, dass so sie nicht escapten Werte in deinem String $sql landen. Denn du hast keine Platzhalter in dem String benutzt. Schau dir mal das PHP Manual an, da gibts Beispiele: ;-)
http://de3.php.net/sprintf
Xong - Di 26.02.08 11:04
chrisdrury hat folgendes geschrieben: |
| Also wäre das die Mindestanforderung? |
Japp! Wobei du die Inhalte von $_GET nicht noch extra zwischenspeichern musst.
Tut mir leid, dass ich mir für die Erklärung von CGI noch keine Zeit genommen habe. Wenn noch Bedarf besteht, tue ich das gern.
LG,
Xong
chrisdrury - Di 26.02.08 11:29
Xong hat folgendes geschrieben: |
Tut mir leid, dass ich mir für die Erklärung von CGI noch keine Zeit genommen habe. Wenn noch Bedarf besteht, tue ich das gern.
LG,
Xong |
Bitte gern, wenn dann möchte ich auch alle Möglichkeiten in Betracht ziehen... :wink:
Kalfany - Di 26.02.08 13:19
Solltest du nicht auch irgendeinen Zeitstempel mit abspeichern von wann der Eintrag ist, und den Server in bestimmten Abständen den Server diesen Eintrag / Timestamp erneuern lassen. Denn du willst beim beenden vom Server den eintrag löschnen, was ist aber wenn der Server abschmiert, oder wenn sich die IP vom Server zwischendrin ändert?
Der Timestamp hätte auch den Vorteil das du alte Einträge per Script löschen kannst.
Ich glaube auch das es einen MySQL befehl gibt der INSERT und UPDATE kombiniert (wenn eintrag vorhanden dann update) (ich glaube das es INSERT .... ON DUBLICATE UPDATE ... ist)
chrisdrury - Di 26.02.08 13:41
Kalfany hat folgendes geschrieben: |
Solltest du nicht auch irgendeinen Zeitstempel mit abspeichern von wann der Eintrag ist, und den Server in bestimmten Abständen den Server diesen Eintrag / Timestamp erneuern lassen. Denn du willst beim beenden vom Server den eintrag löschnen, was ist aber wenn der Server abschmiert, oder wenn sich die IP vom Server zwischendrin ändert?
Der Timestamp hätte auch den Vorteil das du alte Einträge per Script löschen kannst.
Ich glaube auch das es einen MySQL befehl gibt der INSERT und UPDATE kombiniert (wenn eintrag vorhanden dann update) (ich glaube das es INSERT .... ON DUBLICATE UPDATE ... ist) |
Danke für den Vorschlag, werde ich wohl mit einbeziehen... :D
chrisdrury - Mi 27.02.08 15:50
Also, dies wäre dann das PHP-Script zum Löschen des Servers aus der Datenbank:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| <?php include("../cgi-bin/einlog.php"); include("funk.php"); $IP=$_GET['IP']; $connect=@mysql_connect($dbHost, $dbUser, $dbPass) or die("F"); $sql= sprintf("DELETE FROM Chat WHERE Ip=$IP", mysql_real_escape_string($IP)); If ($res=send_sql($db,$sql)) {echo "OK";} ?> |
Ist das soweit richtig?
:?:
Xong - Mi 27.02.08 16:11
chrisdrury hat folgendes geschrieben: |
| Ist das soweit richtig? :?: |
Nein. =)
Quelltext
1: 2: 3:
| $sql= sprintf("DELETE FROM Chat WHERE Ip=%s", mysql_real_escape_string($IP)); |
Das hat dir
jaenicke aber schon geschrieben.
sprintf nimmt als erstes Argument einen Formatstring entgegen. Danach kommen so viele Argumente, wie du benötigst.
Quelltext
1:
| string = sprintf('Ich kann zählen: %d, %d und %d!', 1, 2, 3); |
Das ergibt: "Ich kann zählen: 1, 2 und 3!"
Desweiteren ist es
immer von Vorteil bei PHP die Singlequotes (') zu verwenden. Enthaltene Variablen werden dann nämlich nicht ersetzt.
Beispiel:
Quelltext
1: 2: 3:
| $bar = 'Text'; $foo = 'Ich bin ein $bar.'; // Ergibt: "Ich bin ein $bar." $foo = "Ich bin ein $bar."; // Ergibt: "Ich bin ein Text." |
Warum?
So schließt du bestimmte Fehlerquellen aus (die im Manual erläutert werden:
http://de.php.net/manual/de/language.types.string.php [
http://de.php.net/manual/de/language.types.string.php]).
Solltest du Variablen in einen String einfügen wollen, dann machst du das über sprintf oder - ganz simpel - mit dem Verkettungsoperator (+).
(Zu CGI kann ich dir heute abend etwas schreiben. Diesmal aber wirklich. Da bin ich nämlich endlich mal wieder zu Hause! =) )
chrisdrury - Mi 27.02.08 16:26
@ Xong: Danke schön, manchmal dauert es eben etwas länger, bis man's geschnallt hat...
:autsch: :rofl:
chrisdrury - Mi 27.02.08 22:12
So, jetzt habe ich es endlich geschafft, den aktuellen Server aus der Datenbank zu löschen. :dance2:
Hier der Code des Server-Programms:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| try Strings := TStringList.Create; Strings.Add('IP='+IntP); try IdHTTP2.Post('http://www.joerglipinski.de/chat/loeschen1.php', Strings); ShowMessage('Server is offline'); Memo1.Lines.Add('Server is offline since ' + TimeToStr(Time) + ' on ' + DateToStr(Date)); except on E: Exception do begin showmessage(E.Message); Memo1.Lines.Add(E.Message); end; end; finally Strings.Free; end; |
Und hier die dazu gehörende php-Datei:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| <?php include("../cgi-bin/einlog.php"); include("funk.php"); $IP=$_POST['IP']; $connect=@mysql_connect($dbHost, $dbUser, $dbPass) or die("F"); $sql= sprintf("DELETE FROM Chat WHERE Ip='%s'", mysql_real_escape_string($IP)); If ($res=send_sql($db,$sql)) {echo "OK";} ?> |
Damit läuft es soweit, gibt es noch Verbesserungsvorschläge, Bedenken, Anregungen?
:lupe: :les: :zwinker:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!