Clanintern Clanintern Clanintern

Forum

Öffentliche Foren
FORUM: Spiele & Computer THEMA: Kleiner Chat fürs kleine Netzwerk?
AUTOR BEITRAG
jaH.Da.izi

RANG Deckschrubber

#1 - 02.02 11:26

Da ich die ganze Zeit auf der Suche nach neuen Aufgaben bin kam mir die Idee, mal einfach einen kleinen Chat fürs "Heimnetzwerk" zu schreiben. Sollte ja im Prinzip nicht allzu schwer sein. Muss ja auch nicht groß was können.

Ich dachte da evtl. an folgende Struktur:

Netzwerk bestehend aus zum Beispiel 3 Rechnen. Jedem Rechner, also jeder IP wird dann ein Name zugeordnet, damit man später in einem kleinen Fenster "Johannes: Die eigentliche Nachricht..." schreiben kann und nicht immer die IP eingeben muss.

Das war mein erster Gedanke, diesen Chat zu realisieren. Noch nicht richtig chat, aber das Modell ist ja dann erweiterbar. Man könnte später dann ja eine einzige IP verwenden, an die die Nachrichten gesendet werden. Der Rechner dieser IP schreibt dann einfach jede Nachricht in eine Datei, die jeweils immer verteilt wird. Die Datei wird von allen Rechnern dann 1 mal pro Sekunde, oder sowas in dieser Richtung (je nach Rechenleistung, hab da keinerlei Vorstellung!?), ausgelesen.


Was haltet ihr von diesem Prinzip? Vielleicht Vorschläge oder irgendwelche Tips, die das vielleicht etwas verbessern? Hab mich bisher noch nicht sehr viel damit beschäftigt und auch keine Kenntnisse in der Netzwerkprogrammierung.



Welche Sprache würdet ihr empfehlen? Da ich es gerne plattformunabhängig benutzen möchte sollte diese Sprache eben auch plattformunabhängig sein, logisch. Also soetwas wie VB oder C# (ist doch von Microsoft?) fallen da schonmal weg.

Vielleicht C/C++/Perl? Mein Favorit wäre Perl, da ich hier wohl schon am meisten kann. Wie sollte ich das Programm dann "entwickeln"? Ich denke ich muss das für Windows dann richtig kompilieren und eine .exe Datei erstellen oder? Was für Möglichkeiten von "Grafik" hätte ich? Muss wirklich nur ein kleiner Kasten sein, sonst nichts. Die sind ja meines wissens in manchen Windowssprachen schon vorgegeben oder?


Wäre über jede Mithilfe an dem kleinen Projekt dankbar. Achja, Tutorials lesen könnte ich, macht mir aber nicht wirklich spass und ich hatte bisher nicht viel Erfolg damit. Ich habe mir bisher immer ein kleines "Projekt" überlegt und parallel dazu eben Bücher/Hilfen gelesen. Kann so auch am besten lernen :o)

Bis denn, jaH.da.izi
Morath

RANG Deckschrubber

#2 - 02.02 11:52

Mein Vorschlag wär ja java ;-)

Das Verteilen der Nachrichten von den einzelnen Clients lässt sich wohl am elegantesten über sockets lösen. Der Server nimmt dabei die Nachricht von einem Client entgegen und reicht sie sofort an alle anderen angemeldeten Clients weiter.

Ein gutes Tutorial zur Socketprogrammierung in java findest du unter
http://java.sun.com/docs/books/tutorial/networking/TOC.html

es gab im java tutorial auch mal ein Beispiel für eine Client/Server-Anwendung mit dem Spiel Bingo, aber das find ich im Moment leider nicht mehr :-/
vaest´ark // patrick *ich bin hier nicht der depp*

RANG Master of Clanintern

#3 - 02.02 12:29

ich würd die nachrichten einfach per broadcast (multicast vielleicht) verteilen.
dann machst du auf jedem client einfach nen listener-socket auf einem bestimmten port auf und sendest halt einfach den broadcast an diesen port. der listener empfängt die daten dann und verarbeitet die entsprechend.
im lan wäre das die einfachste möglichkeit.

achtung: da brauchst du direkt ein gescheites threading-modell zu, sonst blockiert der listener deine oberfläche/kommandozeile, weil der halt die ganze zeit laufen muss.

(edit)
c# geht mit mono übrigens auch auf linux
cYb - benjamin - status: Praxissemester

RANG Hardcore Ruler

#4 - 02.02 14:34

könnte doch auch ein consolen basierter chat sein

gibts sowas wie ncurses eigentlich auch für windows?
Morath

RANG Deckschrubber

#5 - 02.02 15:14

Auch ein konsolenbasierter Chat sollte Eingaben und Warten auf Broadcasts in zwei verschiedenen Threads abhandeln, sonst kannst du ja entweder nie was schreiben oder während du schreibst nichts empfangen. Ein CB-Funk-Chat sozusagen ;-)
falcon][bac

RANG Deckschrubber

#6 - 02.02 16:27

Grundsätzlich sollte jede Verbindung ihren eigenen Thread haben. Das schließt auch Ein-/Ausgabestreams (Konsole oder GUI) ein, wobei es bei denen nicht so kritisch ist.
Crush (White & Nerdy)

RANG Master of Clanintern

#7 - 02.02 17:26

Bei C/C++ ist das Problem, dass du auf die Betriebssystem API zugreifen musst um auf Netzwerkfunktionen zuzugreifen. Allerdings könntest du eine betriebssystemunabhängige Bibliothek verwenden. Wenn du ein GUI implementieren willst, wirst du darauf eh zurückgreifen müssen.

Wie wäre es mit QT? Ist eine platformunabhängige Grafikbibliothek die auch Netzwerkfunktionen hat.
cYb - benjamin - status: Praxissemester

RANG Hardcore Ruler

#8 - 02.02 21:38

schon klar @ threads ... aber console fänd ich für sowas kleines schicker
jaH.Da.izi

RANG Deckschrubber

#9 - 03.02 02:06

Also ich hab mich jetzt erstmal drangesetzt und irgendwas grafisches erstellt. Danke @Crush für den Tip, habe mich für QT entschieden :o). War aber trotzdem ein langer weg, hatte mich auch in GTK und Win32::GUI versucht, aber dann letzendlich doch QT genommen. Habe auch schon langsam raus wie der Hase läuft. Ein kleines Programm, welches Datensätze aus einer Datenbank ausliest habe ich auch schon geschrieben. Hat zwar jetzt nicht direkt etwas mit meinem eigentlichen Vorhaben zu tun, aber für die Übung in Sachen GUI war das schonmal sehr hilfreich. Morgen gehts dann an die Netzwerkprogrammierung. Mal sehen was draus wird, evtl. bastel ich als "Vorübung" ein kleines Newssystem für meine Datenbank, damit ich mit den Widgets und generell der Positionierung dieser, etwas vertraut werde.

Das heisst jetzt also, ich werde Perl in Verbindung mit QT verwenden. Gefällt mir bisher auch ganz gut :o).

@Morath Hab mich schon entschieden. Java gefiel mir damals, warum auch immer, nicht so wirklich.

@vaest Ist mir noch etwas zu hoch =)

@cyb Spielt ja "im Prinzip" keine Rolle, wie die Ausgabe dann aufgebaut wird, ob mit oder ohne GUI, sei mal dahingestellt. Hast aber eigentlich schon recht! Die Sache ist nur, das Programm werden ein paar andere mitbenutzen, sprich, ich brauch was fürs Auge O_o


@Alle Was genau hat es mit den Threads auf sich?
Crush (White & Nerdy)

RANG Master of Clanintern

#10 - 03.02 03:30

Zum Thema Threads und Netzwerkanwindungen.

Die meisten Netzwerkoperationen sind sogenannte Blocking Calls. Das bedeutet das Programm hängt so lange bis etwas passiert. Beispielsweise sagst du "Lies Daten, die bei Port 12345 ankommen". Dann hängt das Programm so lange bis Daten an dem Port ankommen. Ist natürlich blöd wenn der User in der Zwischenzeit etwas machen will.

Die Lösung für dieses Problem heisst Multithreading. Multithreading ist eine Form von Multitasking. Ein Programm das Multithreading verwendet läuft nicht linear ab, so wie man es als Programmierer gewohnt ist, sondern man hat eine Reihe von Unterprogrammen, die gleichzeitig und unabhängig voneinander laufen. Während ein Thread auf eine Benutzereingabe wartet, kann ein Anderer auf Daten vom Netzwerk warten und ein Dritter die Daten der letzten Eingabe senden.

Darum hat man bei Netzwerkanwendungen neben dem Hauptprogramm für jede Verbindung 2 Threads, einen der sendet und einen der empfängt.

Das große Problem bei Multithreading ist, dass die Threads in der Regel um miteinander kommunizieren zu können auf gemeinsame Daten zugreifen müssen. Man muss dabei bedenken, dass jederzeit jeder Thread auf die gemeinsamen Datenstrukturen zugreifen kann. Wenn ein Thread mit Daten arbeitet und währenddessen ein anderer Thread diese verändert, dann kann das zu Bugs führen, die sehr unregelmäßig auftreten und sich praktisch nicht reproduzieren lassen und dadurch schwer zu lokalisieren sind. Um das zu verhindern gibt es verschiedene Mittel (sogenannte  Mutexe), die dann aber wieder Probleme mit sich bringen können, wenn man sie falsch benutzt (Deadlocks, zum Beispiel).


Ich weis zwar jetzt nicht wie QT das macht, aber bei vielen Netzwerkbibliotheken ist es so, dass das damit verbundene Multithreading vor dem Programmierer versteckt wird und er sich nicht um die damit verbundenen Kopfschmerzen kümmern muss.
[AZWAT]empi*kackekackescheissscheiss*

RANG Master of Clanintern

#11 - 03.02 15:50

das kommt uA darauf an, ob Qt mit eingeschaltetem Multithreading kompiliert wurde (also nich, ob während des kompilierens MT benutzt wurde, sondern die Unterstützung mit einkompiliert wurde)
jaH.Da.izi

RANG Deckschrubber

#12 - 04.02 11:54

Habe jetzt heute Nacht noch einmal etwas rumgestöbert und bin auf Perl/TK gestossen. Habe etwas damit rumgespielt und es gefällt mir bisher am besten. Sieht auch optisch sehr ansprechend aus, so wollte ich das.

Ich glaube die Idee mit dem Chat muss aber noch etwas warten, muss erstmal mit der GUI-Programmierung etwas vorwärts kommen. Ich bastel jetzt gerade ein kleines Programm, welches Datensätze aus einer Datenbank selektiert/updated/einfügt. Könnte man auch als Datenbankchat betrachten (hinterher). Geht auch primär erstmal um den Aufbau eines solchen Programms.

Ich habe aber eine kleine Frage bezüglich der Perl/TK Programmierung, vielleicht kann ja jemand helfen. Wollte jetzt keinen neuen Thread eröffnen, dreht sich ja dennoch um meine Anfangsidee. :o)

Also ich habe mit Perl/TK eine nette Listbox erstellt, die Datensätze aus der Datenbank ausliest. Dieser Listbox kann man dann ja irgendwelche Events zuordnen. Beispiel:

In der Listbox befindet sich:
1
2
3
4
5

Mit einem Doppelklick soll dann ermittelt werden, welcher Datensatz ausgewählt wurde. In diesem Fall würde ich dann einfach die Nummern 1-5 übergeben. Jetzt habe ich aber Zeilen aus der Datenbank, die ich dann durch Doppelklick speziell anzeigen lassen möchte. Also anfangs wird eine Übersicht ausgegeben mit ID, Titel, Inhalt und nach dem Doppelklick möchte ich alle Datensätze dieser Zeile haben. Also ID, Titel, Inhalt, Datum, Nachname, Vorname. Die Anfragen werden aber durch 2 Statements ausgegeben. Besser gesagt, durch Sichten.

In der Listbox befindet sich also:
1 Titel1 Inhalt1
2 Titel2 Inhalt2
3 Titel3 Inhalt3

Für jede Zeile in der Listbox also eine Zeile der Datenbank. Wenn ich jetzt aber zum Beispiel einen dieser Datensätze (bzw. die Zeile) genauer angezeigt haben möchte, würde die Datenbankabfrage mit einem WHERE versehen werden. Also ich benutze ein SELECT-Statement mit einer WHERE-Bedingung. In dieser WHERE-Bedingung soll dann aber nur die ID stehen, die bei einem Doppelklick mitgesendet wurde und nicht die gesamte Zeile (1 Titel1 Inhalt1). Hat jemand eine Idee, wie ich das umsetzen könnte? Kann man evtl. 2 Variablen übergeben? Einmal die ID und einmal eben der Datensatz? Weiss momentan echt nicht genau wie sich das umsetzen lässt, wäre um jede Hilfe dankbar.

Ich hoffe das war verständlich. Ich schreib aber trotzdem nochmal den Gesamtaufbau hier rein.

Das Programm wird gestartet. Oben hat man dann ein Menü indem man "Sicht auswählen" anklicken kann. Wenn dies geschieht, dann wird eine Listbox mit den Namen der Sichten erstellt. Hier kann ich dann per Doppelklick die Sicht auswählen. Mit dieser Sicht startet dann jeweils eine Datenbankabfrage. Ich bekomme Datensätze zurück und gebe diese wiederum in der Listbox aus. Jetzt möchte ich aber einen dieser Datensätze ebenfalls mit Doppelklick auswählen können, sodass sich für diesen Datensatz eine neue Oberfläche aufbaut. Die Anfrage wird dann mit Hilfe der genauen ID in der WHERE-Bedingung erstellt.


So soll das in etwas aussehen. :o)
Morath

RANG Deckschrubber

#13 - 05.02 09:19

"@Morath Hab mich schon entschieden. Java gefiel mir damals, warum auch immer, nicht so wirklich."

Blasphemie!

Öhm, ich seh grad, das ist hier ja ein c++ Thread geworden...

*verdrückt sich ganz schnell*

Viel Erfolg!
jaH.Da.izi

RANG Deckschrubber

#14 - 05.02 13:13

Ne, eher Perl :o)


@Morath Mir gefiel der Aufbau und die Syntax einfach nicht so gut. Mag ja sein, dass Java sehr mächtig und auch für viele Dinge einfach spitze ist, aber wie gesagt,...Geschmackssache. :o)
Hat mir einfach nicht zugesagt. Ist aber auch bei C und C++ so. Mir macht es mehr spass in C zu programmieren als in C++, warum auch immer ;-).


Achja, ich hatte jetzt die Idee, vorerst einfach mal den "net send" Befehl von Windows zu benutzen. Wäre für den Aufbau der GUI ja sowieso irrelevant und an alle gleichzeitig eine Nachricht senden funktioniert auch. Mal schauen,...

Ich befürchte aber, dass ich keine Möglichkeit habe, dass Popup-Fenster zu verbieten oder? Also lieber wäre es mir, wenn unten rechts oder im Programm selber irgendetwas "blinkt" und nicht so aggressiv ins Bild springt. Da seh ich aber, wegen Microsoft, schwarz, richtig? :o)


Ich mach mich trotzdem mal ran. Wäre auf jeden Fall schonmal schöner nen kleines Fenster/Programm zu haben, indem ich eine List mit den Chattern sehe, die ich dann jeweils auswählen kann, um ihnen in nem Feld dann die Nachrichten zu senden. Würde zumindest das lästige tippen von "net send IP/Pc-Name Nachricht" schonmal wegfallen lassen.

Naja wie gesagt, ich schau mal etwas rum, ich halte euch natürlich auf dem laufenden. :o)
Morath

RANG Deckschrubber

#15 - 05.02 15:28

oh, stimmt, ich hatte nur bis zum QT-Posting gelesen :-)

Wenn du lieber c als c++ programmierst, dann hast du anscheinend die schönen Seiten der Objektorientierung noch nicht kennengelernt und das ist dann wahrscheinlich auch der Grund, wieso dir java nicht gefällt ;-)

Aber ich will mal nicht vom Thema ablenken...
jaH.Da.izi

RANG Deckschrubber

#16 - 05.02 17:01

Öhm ich programmiere zwar in Perl, aber irgendwie kommt mir das hier sehr bekannt vor.

http://perl-tutor.de/perl_oo.html


Ich programmiere glaub schon "objektorientiert". Wobei, ich bin jetzt trotzdem verwirrt irgendwie !?



edit: Ne kleine Frage hab ich. Was genau heisst eigentlich dieses foo immer? Also mir ist das jetzt schon öfter begegnet, hab es aber meist einfach mal als "Beispielname" angesehen. Stimmt das so?


editedit: Arghs, wieso komme ich immer erst hinterher auf die Idee die Wikipedia zu benutzen? Wenn es jemand noch gern wissen möchte,... http://en.wikipedia.org/wiki/Foo
[AZWAT]empi*kackekackescheissscheiss*

RANG Master of Clanintern

#17 - 06.02 11:41

perl und OO ist... etwas anders
Crush (White & Nerdy)

RANG Master of Clanintern

#18 - 06.02 18:02

Seit Perl 5 kann man mit Perl auch objektorientiert programmieren. Allerdings wirkt das Ganze doch etwas spartanisch und zusammengehackt. Man merkt dass die Sprache ursprünglich eigendlich nicht dafür gedacht war.
jaH.Da.izi

RANG Deckschrubber

#19 - 11.02 16:02

Ich bin jetzt soweit, dass sich mehrere Clienten verbinden können. Die Clienten bekommen dabei jeweils einen eigenen Unterprozess.

Jetzt würde ich, wie es bei einem Chat nunmal so ist, eingehende Nachrichten am Server, an alle Clients weitersenden. Eine Idee?
Crush (White & Nerdy)

RANG Deckschrubber

#20 - 11.02 16:54

Und da haben wir sie, die Datenstruktur auf die mehrere Threads (bzw. Prozesse) zugreifen müssen um miteinander zu kommunizieren.

Ich weis jetzt zwar nicht wie es bei Perl ist, aber bei C bzw. C++ ist es bei Thread APIs in der Regel so dass man wenn man einen Thread oder Prozess erzeugt diesem einen Pointer geben kann. Normalerweise nutzt man das für einen Pointer der auf eine Datenstruktur zeigt, die alle Daten enthält die der Thread braucht.

Will man jetzt dem Thread etwas mitteilen, zum Beispiel dass er etwas an die Clients senden soll, dann verändert man im Hauptprogramm etwas an dieser Datenstruktur während der Thread die Struktur in regelmäßigen Abständen auf Veränderungen überprüft.

Im Fall eines Chats würde ich in diese Datenstruktur einen String und eine Flag packen. Wenn das Hauptprogramm will, dass dem Client etwas geschickt wird, dann schreibt es die Nachricht in den String und setzt die Flag. Der Thread überprüft dann regelmäßig die Flag und ist sie gesetzt, dann entfernt er sie und sendet den Inhalt des Strings an den Client. Dabei sollte das Lesen und Schreiben des Strings und Flags unbedingt eine Critical Section sein, damit der Client Thread nicht liest während der Hauptthread schreibt und er so eine Mischung aus der ersten und der zweiten Nachricht verschickt.

Die erweiterte Form wäre dann statt des einen Strings eine ganze Message Queue aus Strings zu haben in der auch mehrere Nachrichten zwischengespeichert werden können, so das der Client Thread sich leisten kann seltener zu pollen ohne Angst zu haben dass Nachrichten verschluckt werden wenn zwischen zwei Polls mehrere Nachrichten an ihn geschickt werden.
Morath

RANG Deckschrubber

#21 - 12.02 08:32

"während der Thread die Struktur in regelmäßigen Abständen auf Veränderungen überprüft"

iiiihhh, Polling? Ich steh ja mehr auf Semaphoren ;-)

Zur aktuellen Frage: crush beschreibt das shared memory-Konzept ganz gut, aber so wie er hab ich leider auch keine Ahnung, wie das in Perl genau funktioniert.

Allerdings geht das ja nur, wenn alle Prozesse Zugriff auf die gleiche Datenstruktur haben, so ein richtiges Beispiel für ein Chatprogramm ist das damit nicht grad, eher eine Producer-Consumer Übung (was ja jetzt auch nicht verkehrt sein muss *g*).
falcon][bac

RANG Deckschrubber

#22 - 13.02 14:51

Normalerweise wird sowas mit dem Observer Pattern geregelt.

Jeder Client -genauer jeder Clientprozess meldet bei einer Klasse (ich nenn sie mal Master) an.
(Die Master-Klasse hat eine Liste /Vektor / Array / ... mit allen angemeldeten Clients)
Wenn bei irgend einem Clientthread eine neue Nachricht ankommt, wird diese an den Master weitergereicht. Der Master geht darauf hin seine Clientliste durch und ruft bei jedem Clientthread der Liste die Methode send(nachricht) auf

Wenn ein Client die Verbindung beendet, meldet er sich beim Master ab, woraufhin er da aus der Liste gestrichen wird und entsprechend auch keiner weiteren Nachrichten mehr erhält.
jaH.Da.izi

RANG Deckschrubber

#23 - 22.02 12:43

Muss momentan doch etwas zurückstecken, stehe kurz vorm Abitur und habe nebenbei ja noch ein Online-Browsergame-Projekt am laufen. Hab selbst dafür momentan nichtmal viel Zeit geschweige denn Lust. Das Abitur geht mir etwas auf den Pinsel.

Werd aber trotzdem noch dran weiterarbeiten, aber eben nicht jetzt :o)
Weasel

RANG Ober0wn3r

#24 - 04.03 09:14

Ehm, geht es drum Programmieren zu lernen, oder brauchst du das Programm einfach nur?

Ich frage mich nämlich gerade, wieso du das Rad neu erfindest...
Crush (White & Nerdy)

RANG Deckschrubber

#25 - 04.03 11:07

Der erste Satz des ersten Posts sollte deine Frage beantworten, Weasel.
Weasel

RANG Ober0wn3r

#26 - 09.03 22:29

stimmt, überlesen.