TCP mit Server und Clients

  • Moin,

    Wahrscheinlich ist das hier für einen Guru eher trivial. Deshalb frage ich.

    Mein Problem:
    Ich möchte einen Server und beliebig viele Clients (die sich einloggen können).
    Der Server muss zu jedem Client Daten senden und empfangen können.

    Wie stelle ich das an ?
    Meine Versuche lassen immer nur eine einzige Verbindung zu. Der Server kann also eine Verbindung eingehen und Daten senden sowie empfangen. Wenn ich das Clientskript aber nochmal starte wird keine weitere Verbindung hergestellt. Beende ich den Client und starte ihn neu wird auch keine Verbindung hergestellt.

    Im Anhang mein Versuch.
    Ziel ist wie gesagt nur eine Verbindung zwischen dem Server und seinen Clients. Alles weitere und wie das genutzt wird mache ich selbst. Man kann nur leider kein Haus bauen, wenn das Fundament fehlt...

  • Ich bin auf dem Bereich leider auch kein Skiller, doch folgende Servervariante funktioniert bei mir:

    Spoiler anzeigen
    [autoit]

    Global Const $n_SERVERIP = @IPAddress1, $i_PORT = 29292
    Global $h_MainSocket, $s_Recv, $ah_ConnectedSocket[2], $i_Socket = 1

    [/autoit] [autoit][/autoit] [autoit]

    TCPStartup ()
    OnAutoItExitRegister ("_OnExit")

    [/autoit] [autoit][/autoit] [autoit]

    $h_MainSocket = TCPListen ($n_SERVERIP, $i_PORT)
    If $h_MainSocket = -1 Then Exit
    $ah_ConnectedSocket[0] = -1

    [/autoit] [autoit][/autoit] [autoit]

    Do
    $ah_ConnectedSocket[0] = TCPAccept ($h_MainSocket)
    Until $ah_ConnectedSocket[0] <> -1

    [/autoit] [autoit][/autoit] [autoit]

    While True
    For $i = 0 To $i_Socket - 1
    $s_Recv = TCPRecv ($ah_ConnectedSocket[$i], 256^2)
    If $s_Recv <> "" Then
    ; =====
    EndIf
    Next

    $ah_ConnectedSocket[$i_Socket] = TCPAccept ($h_MainSocket)
    If $ah_ConnectedSocket[$i_Socket] <> -1 Then
    $i_Socket += 1
    ReDim $ah_ConnectedSocket[$i_Socket]
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _OnExit ()
    TCPCloseSocket ($h_MainSocket)
    For $i = 0 To $i_Socket
    TCPCloseSocket ($ah_ConnectedSocket[$i])
    Next
    TCPShutdown ()
    EndFunc ;==> _OnExit

    [/autoit]

    Der Client wird dabei ganz gewöhnlich aufgebaut...

  • Gut. So ähnlich habe ich es jetzt auch gemacht. (erstmal auf 2 Clients limitiert. Aber das kann ja noch beliebig erweitert werden).

  • Du musst alle aufgebauten Sockets am Besten in einem Array speichern, dann hast du quasi eine Liste aus verbundenen Clienten.
    Wenn du prüfen willst ob noch alle Cienten da sind, dann einfach mal Testdaten senden. Sollte er nicht mehr erreichbar sein dann einfach aus dem Array löschen bzw. den Socket schließen.

    Edit: Du musst natürlich ständig nach eingehenden Verbindungen fragen.

    Edit2: TcpListen führt man normalerweise nur einmal am Anfang im Script aus ...

  • Hier mal ein kleines Beispiel-Script für einen TCP-Server:

    Spoiler anzeigen
    [autoit]

    Global $TCPPort = 1234, $TCPMainSocket, $MaxClients = 100, $Client[$MaxClients+1][2]
    $Client[0][0] = 0

    [/autoit] [autoit][/autoit] [autoit]

    TCPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    $TCPMainSocket = TCPListen(@IPAddress1,$TCPPort,$MaxClients)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    ; Neue Verbindungen:
    $NewClient = TCPAccept($TCPMainSocket)
    If $NewClient <> -1 Then _AddClient($NewClient)
    ; Pakete Empfangen:
    If $Client[0][0] > 0 Then
    For $i = 1 To $MaxClients
    If $Client[$i][0] <> False Then
    For $try = 1 To 3
    $Recv = TCPRecv($Client[$i][0],1024)
    If Not @error Then
    _ReceivedData($i,$Recv)
    ExitLoop
    EndIf
    If $try = 3 Then
    _DelClient($i)
    EndIf
    Next
    EndIf
    Next
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _AddClient($Socket)
    If $Client[0][0] < $MaxClients Then
    For $i = 1 To $MaxClients
    If $Client[$i][0] = False Then
    $Client[0][0] += 1
    $Client[$i][0] = $Socket
    $Client[$i][1] = '???'
    ConsoleWrite('new client on slot '&$i&' connected...'&@TAB&'('&$Client[0][0]&'/'&$MaxClients&' slots used)'&@CRLF)
    ExitLoop
    EndIf
    Next
    Else
    TCPSend($Socket,'server_full')
    TCPCloseSocket($Socket)
    ConsoleWriteError('new client not adopted! no more free slots...'&@TAB&'('&$Client[0][0]&'/'&$MaxClients&' slots used)'&@CRLF)
    EndIf
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _DelClient($Slot)
    TCPCloseSocket($Client[$Slot][0])
    $Client[$Slot][0] = False
    $Client[$Slot][1] = ''
    $Client[0][0] -= 1
    ConsoleWriteError('client on slot '&$Slot&' kicked...'&@TAB&'('&$Client[0][0]&' clients left)'&@CRLF)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _ReceivedData($Slot,$Data)
    ConsoleWrite('received the following data on slot '&$Slot&':'&@TAB&$Data&@CRLF)
    EndFunc

    [/autoit]


    Ich denke der Client sollte kein Problem darstellen, solange du nur ein reines Server-Client-Netz möchtest... ;)

    LG
    Christoph :)