Messengerstatus in Messenger integrieren

Curry

Freizeitschrauber(in)
Hallo liebe PCGH Community,

ich bin zur Zeit dabei einen Messenger zu programmieren in .net

Wie bei anderen Messengern wie z.B. ICQ meldet man sich Datenbankbasiert an. Diese ist abgesichert, z.B dass man nach 5 falschen Logins gesperrt wird usw.

Eine Kontaktliste ist nicht das Problem. Dieses habe ich folgendermaßen realisiert:

Datenbankname=Benutzer
-Freunde: {AUFLISTUNG} seiner Freunde mit Timestamp fürs adden usw.


Nun zum eigentlichen Problem:
Ich habe bloss das Problem, dass ich einen onlinestatus für jeden Benutzer haben möchte.

Wie schaffe ich dieses zu realisieren, OHNE einen riesigen Datentraffic zu erzeugen?

Ich hatte erst überlegt das mit einem Boolwert in der Datenbank zu realisieren, jedoch schließen manche Anwender einfach den Messenger und somit wird der Datenbankwert nicht geändert.

Mit der Pingmethode lässt sich dieses Vorhaben auch nicht realisieren, da viele Router dieses blocken. Außerdem können Benutzer off sein, aucgh wenn ihr PC läuft udn ich somit eine Ping-Request erhalte.


Habt ich vllt Ideen?
Benötigt ihr weitere Informationen?

Wie machen das die großen Messenger wie MSN,Skype oder ICQ?


MfG

Curry
 
Nutzt du eine Client-Server-Architektur oder verbinden die User sich direkt zur DB?

Im Falle von ersteren:
a) im Server den Onlinestatus speichern (Liste aller User, die Online sind)
b) der Socket-Disconnect kann erkannt werden und der Status in der DB geändert werden
c) Diese Art von Ping wird meistens nicht über "Ping" (also ICMP Packete) gemacht, sondern über das Netzwerkprotokoll der Anwendung

Sind jetzt so drei dinge, die mir spontan eingefallen sind ^^
 
Also ich kenn mich jetzt mit .net nicht so aus, aber gibt es nicht nen destruktor für das gesamte programm, dann könnteste ja damit den boolean auf false setzen. Ansonsten ist doch der traffic garnicht so groß wenn der client jede minute nur kurz den server anpingt oder so.

Edit: Zu langsam.
 
@bingo88 Ich habe bisher das Login gemacht. Und dabei verbindet sich das PRogramm zu einem SQL Server. Bin noch nicht ganz so helle in C#. Vllt könntet ihr mir bisschen helfen, wie ich das am besten realisiere
 
Normalerweise besitzt so ein Chat einen separaten Server, der die Logik (Benutzerverwaltung etc.) übernimmt (es gibt auch peer-2-peer Netze, da sieht das anders aus). Im klassischen Client-Server modell sähe das so aus:

DB-Server <- SQL etc. -> dein Server <- dein Netzwerkprotokoll -> dein Client
 
Könnte ich jemand dafür begeistern da mal rein zuschauen?

Ich stehe da ein bisschen aufm Schlauch
 
Ich denke ich werde das mit einem Server machen.
Gibt es eine Möglichkeit dem Server einen befehl zuschicken?

z.B. Send (EmpfängerIP, Nachricht) oder so?
 
Haha, ich arbeite gerade an was ähnlichen ... Zufälle gibst! :D

Wie weit bist du denn? Hast du dir denn schon gedanken gemacht wie die Kommunikation genau laufen soll? :huh:
 
Ja wenn du keine bestehende Bibliothek nutzt, musst du das selbst implementieren (sprich: eigenes Protokoll entwerfen und implementieren).
 
Ich hatte mir das folgendermaßen vorgestellt:

User anschreiben:

  • Message inkl. UserID an Server senden
  • Server fragt IP anhand der UserID ab (UserID=Ähnlich ICQ Nummer/In DB vorhaden)
  • Baut Netzwerkstream zum Nutzer auf
  • Sendet Nachricht via TCPClient
Ist warscheinlich total affig, aber das ist dsa, was ich so bisher kann.

Mein Derzeitiges Problem:
befehle an den Server zu senden.
bsp:
Sende (Nachricht, Userid)

[Also die Trennung von Befehl (Sende) und der Nachricht]

Bin für bessere Vorschläge immer gerne zu haben.
 
Wenn ich das richtig verstehe läuft alle Kommunikation über den Server oder? Damit könntest du, je nachdem wie das Programm nachher eingesetzt werden soll, schon mal recht viele Resourcen für ein privates Projekt binden. Aber das nur mal am Rande. ;)

Wenn du die Serversoftware selber machst, was du eh machen musst wenn du kein vorgefertigtes Protokoll verwenden willst, dann ist das Senden von Nachrichten doch eine Recht einfache Sache.

  1. Nachricht im Client schreiben.
  2. Zieladresse (deine UserID) mit der Nachricht an den Server senden. (du musst ja eh ein Protokoll definieren, dazu gehört dann halt auch das senden und empfangen)
  3. Der Server kann die Absendeadresse ja durch die geöffnete Verbindung bestimmen.
  4. Schauen ob eine aktive Verbindung zum Ziel besteht und senden (ansonsten speichern?)
  5. Empfang der Nachricht am besten den Server bestätigen lassen
  6. Bestättigung an an den sendenen Client weiter geben.
 
Wie wir gerde geschrieben haben, versuche ich das gerade auch.

Jedoch frage ich mich, wie ich soein Protokoll entwickeln soll.
 
Du musst dir überlegen, was du alles brauchst (also welche Nachrichten, z. B. Chat-Nachricht) und wie die einzelnen Nachrichten aufgebaut sein sollen.

Nehmen wir mal eine einfache Message-Nachricht an. Benötigte Daten:
- Sender
- Empfänger
- Nachrichteninhalt

Das müsstest du dann in eine geeignete Datenstruktur verpacken, die du dann über das Netzwerk versenden kannst. Dabei musst du dich fragen, ob du ein Binär- oder Textprotokoll (z. B. XML) nutzen willst. Der leichteste Teil ist eigentlich das Versenden und Empfangen von Paketen, die Schwierigkeit liegt eher in der Programmlogik (Behandeln von Nachrichten, Session-Management, etc.). Soetwas sauber und gut zu entwickeln ist nicht trivial und für den Einstieg ein sicherlich sehr frustrierendes Projekt.
 
Genau da liegt mein PRoblem.

Ich kann dem Server natürlich massenhaft Daten/Pakete schicken, aber der Server muss eben wissen, was damit machen soll..

An diesem PRobleme bin ich eben gerade.

Hat da jemand einen Plan/Tipps?
 
Dieser Kram erfordert normalerweise einiges an Entwurfsarbeit, das kann ich dir nicht abnehmen, da nur du weißt, was dein Programm alles können soll. Ich versuch es mal mit einem kleinen Beispiel (Textnachricht senden):

+ Client A sendet Nachricht an Client b:
->Nachricht: typ=Textnachricht sender=A empfänger=B text="Hallo, B!"

+ Server empfängt Nachricht von Client A:
->Nachrichtentyp abfragen => Textnachricht
->Empfänger ermitteln => B
->B in der Liste der verbundenen Clients suchen (nennen wir das jetzt mal die "Session" von B)
->Falls gefunden: Sende Nachricht an Client B, ansonsten sende Fehlermeldung an A oder was auch immer

+ Client B emfängt Nachricht von Client A
->Nachricht anzeigen

Das steckt teilweise mehr Aufwand hinter, als auf dem ersten Blick vielleicht zu sehen ist. Groß Fehlerprüfen ist hier natürlich auch noch nicht enthalten (z. B. darf A überhaupt senden und B empfangen?).
 
Hier meine Methode zum Senden:

static void Senden(string Nachricht)
{
Byte[] myByte;
TcpClient myClient = new TcpClient("127.0.0.1", 21);
NetworkStream Verbindung = myClient.GetStream();
Verbindung.Write(myByte, 0, myByte.Length);
Console.ReadLine();
}



Und zum Empfangen:

TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
data = null;
NetworkStream stream = client.GetStream();
int i;
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);



------------------------------------------------------------

Also von Client zu Client habe ich das hinbekommen.

Jetzt stellt sich die Frage wie ich das ganze über einen Server realisiere, der die BEfehle inkl. der Daten(Empfänger,Sender,Text...) auseinanderhalten kann
 
Du könntest zum Beispiel ein threadbasiertes Modell nehmen. Dabei wird für jede eingehende Connection am Server ein eigener Thread gestartet, der auf Nachrichten wartet (und diese behandelt). Du kannst dann zu dieser Verbindung noch zusätzliche Informationen speichern (bzw. du musst), z. B. ob zu dieser Verbindung ein User gehört und wenn ja, welchen Namen er hat. Alle Verbindungen musst du dann noch irgendwo speichern, möglichst mit einfacher Identifizierbarkeit. Wenn z. B. User A ne Nachricht an User B schicken will, musst du ja auch irgendwie wissen, wo die hin soll (sprich: welche Verbindung dafür verantwortlich ist). Du hast dir da nicht grade ne einfache Sache für den Einstieg ausgedacht :ugly:
 
Genauso habe ich es vor^^

Das Grundgerüst ist soweit auch fertig.

Ich übergebe die Befehle an den Server in einem Byte

Hierzu setze ich feste BEfehlsketten mit Werten zusammen.
BSP:
Byte="Send12345678998765432100Hallo"
Pos 0-3=> Befehl="Send"
Pos 4-13=>Absender="123456789"

Pos 13-22=>Emfänger="987654321"
Pos 23,24=> Variablen (z.B Falls eine Dateiübertragung läuft"
Pos 25-Ende=>Nachricht="Hallo"

Ich will die Werte der Positionen in einem XML Dokument ablegen udn auslesen.

Die ganzen Internettutorials helfe mir dabei sehr wenig.

XML

<Commands>
<Send>
<cmdlang>4</cmdlang>
<Absender>9</Absender>
<Emfänger>9</Emfänger>
<Variablen>2</Variablen>
</Send>

<Recv>
<cmdlang>6/cmdlang>
<Absender>9</Absender>
<Emfänger>9</Emfänger>
<Variablen>5</Variablen>
</Recv>

</Commands>


Wie kann ich genau DEN Wert auslesen, den ich genau suche.
Anwendungsbeispiel:

Ich baue einen String auf zum Versenden einer Textnachricht. Der Empänger(Server) bekommt die und möchte wissen, welche Substrings er sich herausschneiden muss.
Dazu soll er im XML Dokument nach "Recv" suchen. Und dann
int cmdlang= *HIER SOLL DIE ABFRAGE DES TAGS HIN,WElCHES UNTER "Recv" STEHT*
 
Wenn du es schon mit XML machen willst, kannst du auch direkt XML-Dokumente verschicken & parsen...

Bleiben wir mal bei einem einfachen Texprotokoll und betrachten beispielsweise "SEND":
SEND 12345 12346 Hallo, Welt!

=> Aufbau: <Nachrichtentyp><Trennzeichen><Sender-ID><Trennzeichen><Empfänger-ID><Trennzeichen><Nachricht>

Dein Protokoll legt fest, welcher Nachrichtentyp welche Struktur hat. Bspw. hat SEND die obige Struktur. Das heißt wenn der Server ein SEND empfängt weiß er, dass es insgesamt 4 Felder gibt, die jeweils durch ein eindeutiges Trennzeichen getrennt sind. Das erste Feld stellt den Nachrichtentyp dar, das zweite die ID-Nummer des Senders, das dritte die ID-Nummer des Empfängers und das letzte Feld die eigentliche Nachricht (da können Trennzeichen dann auch ignoriert werden, im Falle von Leerzeichen z. B.).

Alternativ könnte man auch die Länge der einzelnen Felder mitschicken, das erspart Probleme falls das Trennzeichen im Text vorkommen kann:
SEND|5|12345|5|12346|12|Hallo, Welt!
Die |-Striche habe ich jetzt nur zum verdeutlichen eingetragen, die gehören da sosnt nicht rein!
 
Zurück