

Imports System.Net, System.Net.Sockets
Imports System.Text
Imports System.Threading
Imports VERAG_PROG_ALLGEMEIN


Public Class cMessangerListender
    Dim serverSocket As Socket = Nothing
    Dim clientSocket As Socket
    Dim byteData(1023) As Byte

    Public Shared boolInitAufschub As Boolean = False
    Public Shared boolFSSAtlas As Boolean = False
    Public Shared boolDatenserver As Boolean = False

    Dim splitPanelDefaultHeight As Integer = 0

    Public Sub START()
        DIENST_InitSocket() 'initialisieren
    End Sub

    Sub DIENST_InitSocket()
        Try

            If serverSocket IsNot Nothing AndAlso serverSocket.IsBound Then
            Else
                If serverSocket IsNot Nothing Then Exit Sub 'Falls es schon läuft
                serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                Dim IpEndPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8800)
                serverSocket.Bind(IpEndPoint)
                serverSocket.Listen(5)
                serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)

            End If

        Catch ex As Exception
            'LEIDER KEINE ANDRES LÖSUNG
        End Try
    End Sub

    Private Sub OnAccept(ByVal ar As IAsyncResult)
        clientSocket = serverSocket.EndAccept(ar)
        serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
        AddClient(clientSocket)
    End Sub

    Delegate Sub _AddClient(ByVal client As Socket)
    Private Sub AddClient(ByVal client As Socket) ' Neunen Client hinzufügen
        'If InvokeRequired Then
        '    Invoke(New _AddClient(AddressOf AddClient), client)
        '    Exit Sub
        'End If
        ' writeToFrmLog(client, "", "Verbindungsaufbau.. ")
        Send("ConSuccess", client) ' Der Client bekommt die Nachricht, dass die Verbindung steht...
        '... jetzt kann der Client senden, der Server horcht...
        clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
                                 New AsyncCallback(AddressOf OnRecieve), clientSocket)
    End Sub

    Private Sub Send(ByVal msg As String, ByVal client As Socket) 'An den Client senden
        Dim sendBytes As Byte() = Encoding.BigEndianUnicode.GetBytes(msg)
        client.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
    End Sub
    Private Sub OnSend(ByVal ar As IAsyncResult)
        Dim client As Socket = ar.AsyncState
        client.EndSend(ar)
    End Sub

    Private Sub OnRecieve(ByVal ar As IAsyncResult) '  Wenn ein Task-Befehl vom Client empfangen wurde
        Dim client As Socket = ar.AsyncState
        Try
            client.EndReceive(ar)
            Dim bytesRec As Byte() = byteData
            Dim message As String = Encoding.BigEndianUnicode.GetString(bytesRec) '.Replace(Convert.ToChar(0), "")
            Dim s As String = Read(message, client)
            If s <> "" Then Send(s, client) ' Die Aufgabe wird abgearbeitet, der Client bekommt bei Fehler eine Antwort...
        Catch ex As Exception
            client.Shutdown(SocketShutdown.Both)
            client.Close()
        End Try
    End Sub
    Private Sub ListView1_SelectedIndexChanged(sender As Object, e As EventArgs)

    End Sub

    Delegate Function _Read(ByVal msg As String, client As Socket, messageFile() As Byte, fileName As String)
    Private Function Read(ByVal msg As String, client As Socket, Optional messageFile() As Byte = Nothing, Optional fileName As String = "") As String
        'If InvokeRequired Then
        '    Invoke(New _Read(AddressOf Read), msg, client, messageFile, fileName)
        '    Return ""
        'End If
        msg = msg.Replace(Convert.ToChar(0), "")
        ' MsgBox("MESSSSS:::::::::::: " & msg)
        Select Case msg
            Case "test"   'nur ein Test, des Ergbnis ist immer Positiv
                ' writeToFrmLog(client, "test", "test ")
                ' Return "Task successful"
                Send("Task successful", client) 'Client-Mittelung
            Case "NEW_MESSAGE"   'der Task initAufschubkonten wird aufgerufen
                ' MsgBox("NEW_MESSAGE!!!!!")
                '   If Not boolInitAufschub Then Me.writeToFrmLog(client, "initAufschubkonten", "Abgebrochen - Task nicht aktiv " & msg) : Return "Task inactive"

                ' die eigentliche Funktion wird in einem Tread aufgrufen
                Dim thread As New Thread(AddressOf NEW_MESSAGE)
                thread.IsBackground = True
                'thread.Start(client)
                thread.Start()

                'Ein zweiter Thread kontrolliert, ob die Funktion nach einer gewissen Zeit noch läuft und beendet diese ggf.
                'Dim st As New Thread(AddressOf stopThread)
                'st.IsBackground = True
                'Dim param_obj(3) As Object
                ''Übergabeparameter des 2. Threads
                'param_obj(0) = thread
                'param_obj(1) = client
                'param_obj(2) = 60
                'st.Start(param_obj)

                'Send("Task successful", client) 'Client-Mittelung

                Return ""


        End Select

        Return "Task not found"
        ' Me.writeToFrmLog(client, "", "ERROR: Undefinierter Task: " & msg)

    End Function

    Sub NEW_MESSAGE()
        VERAG_PROG_ALLGEMEIN.cMessenger.NEW_MESSGE = True
        '     MsgBox("jojo")
        'For Each openForm In Application.OpenForms()
        '    If TypeOf (openForm) Is frmMessenger Then
        '        'MsgBox("Sendungsfenster bereits geöffnet!")
        '        'CType(openForm, frmSendungsdetailsNEU).BringToFront()
        '        'Return Nothing
        '        CType(openForm, frmMessenger).REFRESH_CHAT()
        '        CType(openForm, frmMessenger).btnTEST.Visible = True
        '        Exit For
        '    End If
        'Next
    End Sub

    Sub stopThread(param_obj As Object) 'Stoppt einen Hauptthread nach einer gewissen Anzahl von Sekunden; Übergabeparameter: Object { Tread, clientSocket, SekundenToTimeout }
        Thread.Sleep(param_obj(2) * 1000) ' Hier wird soviele Senkunden gewartet, wie in den Übergabeparametern definiert wurde.
        If param_obj(0).IsAlive Then
            param_obj(0).Abort() ' Wenn der Hauptthread noch immer läuft, wird er jetzt beendet.
        Else
            Exit Sub
        End If
        Send("Task timeout", param_obj(1)) 'Client-Mittelung
        'Me.writeToFrmLog(param_obj(1), "ERROR: Task wurde aufgrund eines Timeouts abgebrochen.") 'Log-Mittelung
    End Sub





    ''Threadsichere Funktion zum schreiben in die TextBox:
    'Delegate Sub writeToFrmLogCallback(ByVal client As Socket, ByVal nameTask As String, ByVal text As String)
    'Public Sub writeToFrmLog(ByVal client As Socket, ByVal nameTask As String, ByVal text As String)

    '    ' InvokeRequired required compares the thread ID of the
    '    ' calling thread to the thread ID of the creating thread.
    '    ' If these threads are different, it returns true.
    '    If Me.txtLog.InvokeRequired Then
    '        Dim d As New writeToFrmLogCallback(AddressOf writeToFrmLog)
    '        Me.Invoke(d, New Object() {client, nameTask, text})
    '    Else
    '        Dim remoteIpEndPoint As IPEndPoint = client.RemoteEndPoint
    '        Me.txtLog.Text &= Now.ToString("dd.MM.yyyy HH:mm ") & nameTask & " (" & remoteIpEndPoint.Address.ToString & "): " & text & vbNewLine
    '        If Me.txtLog.Lines.Count > 35 Then
    '            Dim arr As String() = Me.txtLog.Lines
    '            Me.txtLog.Text = ""
    '            For i = arr.Count - 35 To arr.Count - 1
    '                Me.txtLog.Text &= arr(i) & vbNewLine
    '            Next i
    '        End If
    '    End If
    '    Me.txtLog.SelectionLength = 0
    'End Sub

    'Public Sub writeToFrmLog(ByVal nameTask As String, ByVal text As String)
    '    Me.txtLog.Text &= Now.ToString("dd.MM.yyyy HH:mm ") & nameTask & ": " & text & vbNewLine
    '    If Me.txtLog.Lines.Count > 35 Then
    '        Dim arr As String() = Me.txtLog.Lines
    '        Me.txtLog.Text = ""
    '        For i = arr.Count - 35 To arr.Count - 1
    '            Me.txtLog.Text &= arr(i) & vbNewLine
    '        Next i
    '    End If
    'End Sub



    'Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 'geht nicht
    '    clientSocket.Close()

    '    If clientSocket.Connected Then
    '        clientSocket.Shutdown(SocketShutdown.Both)
    '        clientSocket.Close()
    '    End If
    '    clientSocket.Disconnect(True)

    '    txtInitAufschubStatus.Text = "angehalten"
    '    txtInitAufschubStatus.ForeColor = Color.DarkRed
    'End Sub

    Public Sub STOP_MSG_LISTENDER()
        clientSocket.Shutdown(SocketShutdown.Both)
        clientSocket.Close()
        serverSocket.Shutdown(SocketShutdown.Both)
        serverSocket.Close()
        serverSocket = Nothing
        DIENST_InitSocket()
    End Sub





    Private Result As Object = Nothing 'Store the worked result of abc()
    Private Sub Worker(ByVal state As Object)
        Dim are As AutoResetEvent = DirectCast(state, AutoResetEvent)
        ' do anything you want here:





        Dim result As Integer = 0
        'result = abc(input_val);

        SyncLock Me.Result
            Me.Result = result
        End SyncLock
        are.[Set]()
    End Sub
    'Private Sub method()

    '    Const TimeOut As Int32 = 5000
    '    Dim [handles] As WaitHandle() = New WaitHandle() {New AutoResetEvent(False)}

    '    ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Worker), [handles](0))
    '    Dim finished As Boolean = WaitHandle.WaitAll([handles], TimeOut, True)
    '    'ThreadPool.RegisterWaitForSingleObject ()

    '    If finished Then
    '        ' step 2
    '        MessageBox.Show("Worker function finished sucessfully, go to Step2")
    '    Else
    '        ' step 3
    '        MessageBox.Show([String].Format("Worker function time out({0})!, go to Step3", TimeOut))
    '    End If
    'End Sub


End Class

Public Class cServerClient
    Dim clientSocket As Socket
    Dim byteData(1023) As Byte
    Dim doThis As String
    Dim params() As String
    Public status As String = "begin"
    ' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    '     begin()
    ' End Sub

    Public Event FunctionFinished(ByVal sender As Object, ByVal e As FunctionFinishedArgs)


    Public Sub begin(ip, doThis_tmp, Optional params() = Nothing)
        Try

            doThis = doThis_tmp
            params = params
            Dim timeOut As Integer = 60
            Select Case doThis
                Case "test" : timeOut = 5 ' nach 5 Sekunden wird abgebrochen
                Case "NEW_MESSAGE" : timeOut = 5 ' nach 120 Sekunden wird abgebrochen
                    'Case "initAufschubkonten" : timeOut = 60 ' nach 60 Sekunden wird abgebrochen
            End Select

            'Ein Thread kontrolliert, ob die Funktion nach einer gewissen Zeit noch läuft und beendet diese ggf.
            'Dim st As New Thread(AddressOf stopThread)
            'st.IsBackground = True
            'Dim param_obj(1) As Object
            ''Übergabeparameter des 2. Threads
            'param_obj(0) = timeOut
            'st.Start(param_obj)


            clientSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            Dim ipAddress As IPAddress = IPAddress.Parse(ip)

            ' Dim ipAddress As IPAddress = ipAddress.Parse("192.168.0.90")
            Dim ipEndPoint As IPEndPoint = New IPEndPoint(ipAddress, 8800)
            clientSocket.BeginConnect(ipEndPoint, New AsyncCallback(AddressOf OnConnect), Nothing)
            status = "beginConnect"
            '   endconnect(clientSocket)

        Catch ex As Exception
            MsgBox(ex.Message & ex.StackTrace)
        End Try

    End Sub

    Public Sub waitTillFinished()
        While Not (status = "TaskError" Or status = "TaskSuccess")
            'wait
        End While
        'Return True
    End Sub

    Private Sub OnConnect(ByVal ar As IAsyncResult)
        Try
            clientSocket.EndConnect(ar)
            clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
                                      New AsyncCallback(AddressOf OnRecieve), clientSocket)
        Catch ex As Exception
            '  MsgBox("Verbindung zum Server konnte nicht aufgebaut werden!")
        End Try
    End Sub

    Private Sub OnSend(ByVal ar As IAsyncResult)
        Dim client As Socket = ar.AsyncState
        client.EndSend(ar)
    End Sub
    Private Sub Send(ByVal msg As String, ByVal client As Socket)
        Dim sendBytes As Byte() = Encoding.BigEndianUnicode.GetBytes(msg)
        client.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
    End Sub
    Public Function ByteArrayToTextString(ByRef Barr() As Byte) As String
        Dim enc As System.Text.Encoding = Encoding.BigEndianUnicode
        Return enc.GetString(Barr)
    End Function

    Private Sub OnRecieve(ByVal ar As IAsyncResult)
        Try
            Dim client As Socket = ar.AsyncState
            client.EndReceive(ar)
            Dim bytesRec As Byte() = byteData
            Dim message As String = Encoding.BigEndianUnicode.GetString(bytesRec)
            '  MsgBox("FROM SERVER: " & message)
            Dim b(1023) As Byte

            ' MsgBox("SERVER RECIEVE: " & Encoding.BigEndianUnicode.GetString(b))

            byteData = b
            Read(message)
            clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None,
                                      New AsyncCallback(AddressOf OnRecieve), clientSocket)

        Catch ex As Exception
            '   MsgBox("Verbindung zum Server wurde unterbrochen!")
        End Try
    End Sub

    Delegate Sub _Read(ByVal msg As String)
    Private Sub Read(ByVal msg As String)
        'If frmMain.InvokeRequired Then
        '    frmMain.Invoke(New _Read(AddressOf Read), msg)
        '    Exit Sub
        'End If

        'frmMain.icoVERAGMonitoring.Visible = False

        'if richtige nsachricht
        '  Dim asciis As Byte() = Encoding.BigEndianUnicode.GetBytes(msg)
        '  Dim a As Char = msg(msg.Length - 1)
        ' msg = msg.Replace(a, "")
        ' MsgBox(msg.Length)

        ' MsgBox(msg(msg.Length - 1))
        ' MsgBox(msg(msg.Length - 1))
        '      MsgBox(Asc(msg(msg.Length - 1)))
        ' MsgBox(Asc(msg(msg.Length - 2)))
        msg = msg.Replace(Convert.ToChar(0), "")
        Try

            '  MsgBox("-" & msg & "-" & vbNewLine & "ConSuccess" & "-")
            If msg = "ConSuccess" Then
                status = "ConSuccess"
                Select Case doThis
                    Case "test"
                        Send("test", clientSocket)
                        status = "sendTask"
                    Case "NEW_MESSAGE"
                        Send("NEW_MESSAGE", clientSocket)
                        status = "sendTask"
                End Select

                '  MsgBox("!!!!!ConSuccess --> initAufschubkonten")
                '   Send("FSSAtlasStart", clientSocket)
                'Send("test", clientSocket)
                'Send("initAufschubkonten", clientSocket)

                'ElseIf msg = "Task successful" Then
                '    status = "TaskSuccess"
                '    clientSocket.Disconnect(False)
                '    clientSocket.Shutdown(SocketShutdown.Both)
                '    clientSocket.Close()
                '    'endconnect(clientSocket)'geht ned
                '    '  MsgBox("Task erfolgreich!", vbSystemModal, doThis)
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.OK, "Task erfolgreich!"))
                'ElseIf msg = "Task not found" Then
                '    MsgBox("SERVERERROR: Der Dienst wurde nicht gefunden!", vbSystemModal, "NEW_MESSAGE")
                '    status = "TaskError"
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "SERVERERROR: Der Dienst wurde nicht gefunden!"))
                'ElseIf msg = "Task inactive" Then
                '    MsgBox("SERVERERROR: Der Dienste ist nicht aktiv!", vbSystemModal, "NEW_MESSAGE")
                '    status = "TaskError"
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "SERVERERROR: Der Dienste ist nicht aktiv!"))
                'ElseIf msg = "Task timeout" Then
                '    MsgBox("SERVERERROR: Der Dienst wurde wegen einer Zeitüberschreitung abgebrochen!", vbSystemModal, "NEW_MESSAGE")
                '    status = "TaskError"
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "SERVERERROR: Der Dienst wurde wegen einer Zeitüberschreitung abgebrochen!"))
                'ElseIf msg = "Task error" Then
                '    MsgBox("SERVERERROR: Server-Fehler!", vbSystemModal, "NEW_MESSAGE")
                '    status = "TaskError"
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "SERVERERROR: Server-Fehler!"))
                'Else
                '    MsgBox("SERVER_NACHRICHT NICHT VERSTANDEN: " & msg, vbSystemModal)
                '    status = "TaskError"
                '    RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "SERVER_NACHRICHT NICHT VERSTANDEN: " & msg))

                '    clientSocket.Shutdown(SocketShutdown.Both)
                '    clientSocket.Close()
            End If

        Catch ex As Exception
            MsgBox("Verbindungs-Fehler beim Senden", vbSystemModal)
            status = "TaskError"
            RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "Verbindungs-Fehler beim Senden"))
            clientSocket.Close()
        End Try
        ' byteData = Encoding.BigEndianUnicode.GetBytes("")

    End Sub



    Sub stopThread(param_obj As Object) 'Stoppt einen Hauptthread nach einer gewissen Anzahl von Sekunden; Übergabeparameter: Object { Tread, clientSocket, SekundenToTimeout }
        Thread.Sleep(param_obj(0) * 1000) ' Hier wird soviele Senkunden gewartet, wie in den Übergabeparametern definiert wurde.
        If status = "TaskError" Or status = "TaskSuccess" Then Exit Sub
        status = "TaskError"
        Try
            clientSocket.Disconnect(False)
            clientSocket.Shutdown(SocketShutdown.Both)
            clientSocket.Close()
        Catch ex As Exception
            MsgBox(ex.Message & ex.StackTrace)
        End Try

        RaiseEvent FunctionFinished(Me, New FunctionFinishedArgs(FunctionFinishedArgs.EventResult.ERR, "Task wurde aufgrund eines Timeouts vom Client abgebrochen."))
        MsgBox("ERROR: Task wurde aufgrund eines Timeouts vom Client abgebrochen.") 'Log-Mittelung
    End Sub


End Class

Public Class FunctionFinishedArgs
    Inherits EventArgs
    'das was man später unter e sehen kann
    Public Result As EventResult
    'hier - als Beispiel - einfach eine Enum
    Public Enum EventResult
        OK
        ERR
    End Enum
    Public Message As String
    'Zum übergeben der Parameter
    Public Sub New(ByVal r As EventResult, m As String)
        Result = r
        Message = m
    End Sub
End Class