none
Instant Messager-Vorgehen RRS feed

  • Frage

  • Nachdem ich einen einfacheres Server Client Programm mit TCP geschrieben habe, fühle ich mich nun sicher genung um den Instant Messager zu machen.

    Ich habe mir das vorgehen so gedacht:

    Server:

    1.Thread: Benutereingabe

    2.Thread:Warten auf eingehende Nachrichten bzw. Logins, Register, und anfragen auf alle angemeldeten Nuter.

    3 Thread: Weiterleiten der Nachricht. Soll ich hier einfach einen TCPListener in jedem Cleint verwenden? Würde eine Liste verwenden, mit der foreach Schleife durchgehen, und dann Verbindung aufbauen und versenden.

    Client:

    1.Listbox, aller regestrierten Benutzer, und aller die online sind. In dem SelectionChanged-Event würde ich dann nochmal die Liste vom Server abrufen, und ggF. einen Chat mit einer Listbox aller gesendeten bzw. empfangen Liste und eine Textbox öffnen. Beim senden einer Nachricht dann den Server anfragen, dann eine Nachrichten Klasse senden.

    Nachricht Klasse:

    -Sender

    -Empfänger

    -Inhalt

     Stimmt mein Prinzip so, oder was sollte ich verändern?

    LG

    Dienstag, 13. Oktober 2015 15:20

Antworten

  • Hi,
    die Schleife baust Du mit do...loop auf. In der Schleife prüfst Du, ob es Einträge in einer Warteschlange gibt, die dann nacheinander abgearbeitet werden. Ein Eintrag in der Warteschlange beschreibt, was zu tun ist, z.B., von wem, an wen, welcher Nachrichtentext zu versenden ist. Wenn nichts mehr zu tun ist, dann wartest Du über ein WaitAny auf die nächste Aufgabe oder den Abbruch der Schleife. Sobald sich ein Client meldet, trägst Du in die Wartschlange die nächste Aufgabe ein und informierst mit Set, dass das Warten in der Schleife zu beenden ist und wieder Aufgaben zur Verarbeitung anliegen. Aufgaben können z.B. sein: Warten auf eine Anmeldung, Warten auf eine Nachricht, Versenden einer Nachricht.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert R3turnz Samstag, 17. Oktober 2015 20:13
    Freitag, 16. Oktober 2015 04:36

Alle Antworten

  • Hallo,

    da hätte ich ein paar Fragen zu:

    - soll der Messanger über einen separaten Server betrieben werden oder direkt als Client2Client?

    - Netzwerk oder Internet?

    - Wie sollen sich die Clients finden?

    - Berechtigungen?


    Mittwoch, 14. Oktober 2015 06:28
  • Hallo,

    1.Client-Server-Client

    2.Netzwerk

    3.Auf einem seperaten PC, der aber im gleichen Netzwerk ist.

    4. Ich weiß ncht genau was du meinst.

    LG

    Mittwoch, 14. Oktober 2015 13:42
  • Hi,

    mit der Berechtigung wollte ich nur wissen, ob jeder dem Chat beitreten darf oder nur ausgewählte Personen etc.. Ich habe mal vor vielen Jahren in einem Seminar einen Chatserver in VB.NET programmiert. Hoffe das bringt dich ein bisschen weiter.

    ChatServer: Hierbei handelt es sich um eine Consolen-Anwendung!

    Public Class Client
        Public m_tcpclient As TcpClient
        Public m_server As Server
        Public sr As StreamReader
        Public sw As StreamWriter
        Public name As String
    
        Sub New(ByVal tcpClient As System.Net.Sockets.TcpClient, _
                ByVal server As Server)
            m_tcpclient = tcpClient
            m_server = server
        End Sub
    
        Sub run()
            sr = New StreamReader(m_tcpclient.GetStream)
            sw = New StreamWriter(m_tcpclient.GetStream)
            sw.AutoFlush = True
            name = sr.ReadLine
            m_server.add(Me)
            Try
                While Not sr.EndOfStream
                    Dim zeile As String = sr.ReadLine
                    Dim befehl As String = sr.ReadLine 'Das hier ist die Reihenfolge des Protokolls!!!
                    m_server.verarbeite(name, befehl, zeile)
                End While
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try
            m_server.remove(Me)
        End Sub
    
        Sub writeline(ByVal zeile As String)
            sw.WriteLine(zeile)
        End Sub
    
        Sub werdeGekickt()
            m_server.remove(Me)
        End Sub
    
    End Class
    Module Module1
    
        Sub Main()
            Dim server As New Server
            server.run()
        End Sub
    End Module
    Public Class Server
        Public liste As New List(Of Client)
    
        Sub run()
            Dim ip As System.Net.IPAddress = System.Net.IPAddress.Parse("127.0.0.1")
            Dim tcplistener As New System.Net.Sockets.TcpListener(ip, 1234)
            tcplistener.Start()
            Do
                Dim tcpclient As System.Net.Sockets.TcpClient = tcplistener.AcceptTcpClient
                Dim client As New Client(tcpclient, Me)
                Dim thread As New System.Threading.Thread(AddressOf client.run)
                thread.Start()
            Loop
        End Sub
    
        Sub add(ByVal client As Client)
            liste.Add(client)
        End Sub
    
        Public Sub remove(ByVal client As Client)
            liste.Remove(client)
        End Sub
    
        Sub verarbeite(ByVal name As String, ByVal befehl As String, ByVal zeile As String)
            Select Case befehl
                Case "say"
                    For Each c As Client In liste
                        c.writeline("say")
                        c.writeline(name & " : " & zeile)
                    Next
                Case "quit"
                    For Each c As Client In liste
                        c.writeline("Benutzer " & name & " hat den Chat verlassen!")
                        If c.name = name Then
                            c.writeline("die")
                            c.writeline("")
                            c.werdeGekickt()
                        End If
                    Next
                Case "kick"
                    Dim opfer As Client = Nothing
                    For Each c As Client In liste
                        c.writeline("say")
                        c.writeline(zeile & " wurde von " & name & " gekickt!!")
                        If c.name = zeile Then
                            opfer = c
                        End If
                    Next
                    If opfer IsNot Nothing Then
                        opfer.writeline("die")
                        opfer.writeline("")
                        opfer.werdeGekickt()
                        remove(opfer)
                    End If
            End Select
        End Sub
    
    End Class

    Und hier ist der Client in WindowsForms:

    Public Class FormClient
        Private tcpClient As System.Net.Sockets.TcpClient
        Private sw As System.IO.StreamWriter
        Private sr As System.IO.StreamReader
    
        Private Sub ButtonConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonConnect.Click
            If Me.TextBoxName.Text = "" Then
                MessageBox.Show("Bitte Name eingaben!", "Fehler", MessageBoxButtons.OK)
                Return
            End If
    
            tcpClient = New System.Net.Sockets.TcpClient("localhost", 1234)
            sw = New System.IO.StreamWriter(tcpClient.GetStream)
            sr = New System.IO.StreamReader(tcpClient.GetStream)
            sw.AutoFlush = True
    
            sw.WriteLine(Me.TextBoxName.Text)
    
            Me.TextBoxName.Enabled = False
            Me.ButtonConnect.Enabled = False
            Me.TextBoxAusgabe.Enabled = True
            Me.TextBoxEingabe.Enabled = True
            Me.ButtonSenden.Enabled = True
    
            'Me.TimerChecker.Start()
            Me.BackgroundWorker1.RunWorkerAsync()
    
        End Sub
    
        Private Sub TimerChecker_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerChecker.Tick
    
            If Not tcpClient.Connected Then Me.Close()
            If tcpClient.GetStream.DataAvailable Then
                Dim befehl As String = sr.ReadLine
                Dim zeile As String = sr.ReadLine
                Select Case befehl
                    Case "die"
                        Me.Close()
                        Return
                    Case "say"
                        Me.TextBoxAusgabe.Text &= zeile & vbCrLf
                End Select
    
            End If
        End Sub
    
        Private Sub ButtonSenden_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSenden.Click
            sw.WriteLine(Me.TextBoxEingabe.Text)
            sw.WriteLine(Me.TextBoxBefehl.Text)
            Me.TextBoxEingabe.Text = ""
            Me.TextBoxBefehl.Text = ""
        End Sub
    
        Private Delegate Sub addStringDelegant(ByVal zeile As String)
        Private Delegate Sub quitDelegant()
    
        Private Sub addString(ByVal zeile As String)
            Me.TextBoxAusgabe.Text &= zeile & vbCrLf
        End Sub
    
        Private Sub quit()
            MessageBox.Show("Und Tschüss", "haha")
            Me.Close()
        End Sub
        Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
            Do
                Dim befehl As String = sr.ReadLine
                Dim zeile As String = sr.ReadLine
                Select Case befehl
                    Case "die"
                        Me.Invoke(New quitDelegant(AddressOf Me.quit))
                        Return
                    Case "say"
                        Me.Invoke(New addStringDelegant(AddressOf Me.addString), zeile)
                End Select
                System.Console.Beep(1000, 10)
                System.Threading.Thread.Sleep(1000)
            Loop
        End Sub
    
        Private Sub FormClient_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
        End Sub
    End Class

    ChatClient Form

    Die Form solltest du mit wenigen Clicks zusammengestellt bekommen. Achte mal auf die Befehle die zur Verfügung stehen. 

    Donnerstag, 15. Oktober 2015 05:35
  • Hi,
    wie David bereits bemerkt hat, sollten vor Beginn einige Details festgelegt werden, die als Grundlage für die Lösung dienen. Ich sehe da die folgenden Festlegungen:

    1. Die Server-Funktionalität sollte als selbständige Lösung ohne Benutzereingaben für den eigentlichen Prozess aufgebaut werden.

    2. Zwei Threads in der Client-Lösung reichen: 1. für die Oberfläche, 2. für die Kommunikation.

    3. Für die Kommunikation sollte ein logisches Interface spezifiziert werden, welches den Typ der konkreten Nachricht, den Nachrichteninhalt und ggf. weitere Zustandsinformation enthält, z.B. als serialisierbaren XML-Strom.

    Der Kommunikations-Thread sollte sowohl für Verbindungsaufbau, Login, Statusaustausch und auch die Nachrichten selbst verantwortlich. Er sollte so programmiert werden, dass er über eine "Warteschlange" zyklisch die anstehenden kurz zu haltenden Aktivitäten abarbeitet.

    Ein Beispiel dazu hatte ich auf meiner Homepage veröffentlicht unter multilateraler Chat.

    Viel Spass.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Donnerstag, 15. Oktober 2015 06:08
  • Danke,

    für die Antworten:

    @David: Ich kann leider nur C# bzw. WPF, daher bringt mir der Code erdenklich wenig. 

    1.Ich weiß nicht genau was du meinst.

    2.OK

    3.Ich hatte auch an eine Nachrichten Klasse gedacht. Des weiteren hätte ich einfach einen BinaryWriter/Reader verwendet.

    4.Also eine Liste mit Aufgaben?`WIe genau muss ich mir das vorstellen?

    LG

    Donnerstag, 15. Oktober 2015 12:20
  • Hi,
    ich vermute mal, dass Du mir geantwortet hast.

    Mit Server-Funktionalität meine ich beispielsweise eine Konsolenanwendung, die auf Clients hört und auf jede Anforderung eines Clients eine Antwort zurücksendet. Diese Anwendung läuft auf irgendeinem Rechner und zeigt auf der Konsole maximal ein Protokoll der Arbeit.

    Zwischen Client und Server gibt es unterschiedliche Fragen und Antworten, z.B. Anmelden (wer bin ich); Fragen, wer noch angemeldet ist; Nachricht an einen Client schicken, Nachricht an alle Clients schicken usw. Diese sollte man in eine Datenstruktur packen, z.B. ein Nachrichten-Objekt, welches serialisiert übertragen wird.

    Mit einer Liste von Aufgaben meine ich: "was ist als nächstes zu tun?", z.B. Senden einer Antwort aufgrund einer Anforderung. Wenn beispielsweise alle Clients eine Nachricht bekommen sollen, dann werden entsprechend der angemeldeten Client für jeden Client Aufgaben in die Liste gestellt, die dann zyklisch abgearbeitet werden. Am besten ist dafür ein FIFO-Schlange (Queue) geeignet.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Donnerstag, 15. Oktober 2015 13:01
  • Hey,

    1.Ok, dann hatte ich dich einfach falsch verstanden.

    2.Wie genau kann ich mir die Schleife vorstellen. Ich füge ihr Objekte, die alle von einer Klasse, z.B. Task ableiten, und dann ihre Aufgaben Eigenschaften haben?

    LG

    Donnerstag, 15. Oktober 2015 14:56
  • Hi,
    die Schleife baust Du mit do...loop auf. In der Schleife prüfst Du, ob es Einträge in einer Warteschlange gibt, die dann nacheinander abgearbeitet werden. Ein Eintrag in der Warteschlange beschreibt, was zu tun ist, z.B., von wem, an wen, welcher Nachrichtentext zu versenden ist. Wenn nichts mehr zu tun ist, dann wartest Du über ein WaitAny auf die nächste Aufgabe oder den Abbruch der Schleife. Sobald sich ein Client meldet, trägst Du in die Wartschlange die nächste Aufgabe ein und informierst mit Set, dass das Warten in der Schleife zu beenden ist und wieder Aufgaben zur Verarbeitung anliegen. Aufgaben können z.B. sein: Warten auf eine Anmeldung, Warten auf eine Nachricht, Versenden einer Nachricht.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert R3turnz Samstag, 17. Oktober 2015 20:13
    Freitag, 16. Oktober 2015 04:36