Tcp Server screenshot übertragung zum tcp client

  • Ich bin ziemlich neu in autoit hab ungefähr vor paar wochen angefangen hatte aber schon paar programmier kenntnisse
    mein problem ist das ich versucht hab von einem tcp server regel mäßig screenshots zum client zu schicken aus irgendeinen grund funktioniert es nicht ich hab auch schon versucht meine firewall optionen zu ändern
    hat aber auch nichts gebracht ich hab generell das problem das ich vom server an den client nichts senden kann ich weiß auch nicht wieso ich hab schon sehr viel ausprobiert aber das meiste hat nicht geklappt
    ich hoffe ihr könnt mir helfen :thumbup:
    hier der quellcode vom server:


    #include <ScreenCapture.au3>

    TCPStartup()


    $listen = TCPListen(@IPAddress1, 5900,1)
    If @error Then
    MsgBox(0, "ERROR", "Please check your firewall options")
    EndIf
    Do
    $accept = TCPAccept($listen)
    Until $accept <> -1

    $test = _ScreenCapture_Capture(@MyDocumentsDir & "\screen.jpg\")
    While 1


    $send = TCPSend($accept, $test)
    If @error Then
    MsgBox(0, "error", "Failed to connect")
    EndIf
    WEnd

    Client:


    #include <ScreenCapture.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>

    $ip = InputBox("title","ip?")
    #Region ### START Koda GUI section ### Form=
    $Form2 = GUICreate("Remote Desktop", 615, 440, 192, 124)
    $Pic1 = GUICtrlCreatePic("", 0, 0, 617, 393)
    $Button1 = GUICtrlCreateButton("Show Screen", 8, 408, 595, 25)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    TCPStartup()


    $port = 5900

    $connect = TCPConnect($ip,$port)


    $recv = TCPRecv($connect,2048)

    GUICtrlSetData($Pic1,$recv,2048)

    EndSwitch
    WEnd

  • Es gibt eine Lösung dafür, nennt sich Deskstream, und übermittelt nicht nur Standbild, sondern auch (in Maßen) Video incl. Zooming, Panning und noch andere Kleinigkeiten^^

    Und zum Topic:
    Aus der Hilfe:

    Zitat von _ScreenCapture_Capture

    ...gibt die Funktion ein Handle zu einem HBITMAP zurück.

    Um die (Screenshot)-Datei zu versenden, musst du den Inhalt erst einlesen und dann stückchenweise versenden...
    Beim Server dann wieder zusammensetzen und einen Namen vergeben, speichern, fertig!

    Topic2:
    HIER gibt es eine Anleitung für die Verwendung von TCP.

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (31. Dezember 2012 um 23:42)

  • hey, wie schon gesagt wurde _ScreenCapture_Capture() gibt ein handle zurück, bzw. wenn ein Dateipfad angegeben ist gar nix zurück
    aber auch die tcp verwendung von dir funktioniert so nicht
    TCP macht es uns leider nicht so einfach wie es scheint :)

    hier mal ein paar tipps:
    also auf jedenfall einen port über 10000 nehmen weil die da drunter sind meist schon belegt
    TCPSend und TCPRevc muss in eine Schleife rein, weil wenn du TCPSend jetzt ein 400KB screenshot gibst werden wahrscheinlich nur 20KB gesendet ;)
    und ich würde an deiner stelle Server und Clienten tauschen, also dass der Server du bist und den Screen angezeigt bekommst
    und der Client sich mit dir verbindet und dir den screen schickt, dass macht es einfacher als wenn dann XYZ "Kunden" eine portweiterleitung einrichten müssen, damit du dich connecten kannst ;)

    hier jetzt mal mein lösungsbeispiel:

    Server.au3
    [autoit]

    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    Opt("TCPTimeout", 100)
    OnAutoItExitRegister("_Global_Exit")
    TCPStartup()

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

    ; die Einstellungen kannst du so lassen
    Global $hGUI, $cScreen, $cRefresh, $sTitle = "Remote Desktop", _
    $iServerPort = 12900, $sServerIP = "0.0.0.0", $iMainSocket = -1, $iClientSocket = -1, _
    $sTCPLineBreak = "<START_NEXT_COMMAND>" & @CRLF, $iTCPMaxByte = 256000, $iTCPTimeOut = 2000

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

    $iMainSocket = TCPListen($sServerIP, $iServerPort)
    If @error Then
    MsgBox(16, $sTitle, "Please check your firewall options")
    Exit
    EndIf

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

    ; gui erstellen
    ; => die GUI wird erst sichtbar, wenn ein Client sich connectet hat!
    $hGUI = GUICreate($sTitle, 800, 620)
    $cScreen = GUICtrlCreatePic("", 0, 0, 800, 600)
    $cRefresh = GUICtrlCreateButton("Refresh", 0, 600, 800, 20)

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

    ConsoleWrite("Warten, dass ein Client sich einloggt..." & @CRLF)
    Local $sRevcData, $sRevcDataSeg, $aSplitCommand, $iCommandStep

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

    While 1
    ; wenn kein Client sich connectet hat fragen wir eingehende verbindungen ab
    If $iClientSocket <= 0 Then
    $iClientSocket = TCPAccept($iMainSocket)
    Else
    ; wenn wir ein Clienten haben fragen wir eingehende Daten ab
    $sRevcData = TCPRecv($iClientSocket, $iTCPMaxByte)
    If $sRevcData <> "" Then ; die Do-Until schleife ist, damit wir ALLE daten empfangen und kein teil verloren geht
    Do
    $sRevcDataSeg = TCPRecv($iClientSocket, $iTCPMaxByte)
    If $sRevcDataSeg = "" Then ExitLoop
    $sRevcData &= $sRevcDataSeg
    Until $sRevcDataSeg <> ""

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

    ; falls mehrere Daten gleichzeitig ankommen splitten wir, damit keine Befehle untergehen
    $aSplitCommand = StringSplit($sRevcData, $sTCPLineBreak, 1)
    For $iCommandStep = 1 To $aSplitCommand[0]
    If $aSplitCommand[$iCommandStep] <> "" Then _PhraseGlobalTraffic($aSplitCommand[$iCommandStep])
    Next
    EndIf
    EndIf

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

    Switch GUIGetMsg() ; normales gui handling
    Case $GUI_EVENT_CLOSE
    Exit

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

    Case $cRefresh ; wenn button gedrückt wird, fragen wir neuen screenshot ab
    If $iClientSocket <= 0 Then ContinueLoop
    TCPSend($iClientSocket, "REFRESH_SCREEN" & @CRLF & $sTCPLineBreak)
    EndSwitch
    WEnd

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

    Func _PhraseGlobalTraffic($sPhraseTraffic)
    Local $aPhraseTraffic = StringSplit($sPhraseTraffic, @CRLF, 1)
    If @error Then Return -1
    Switch $aPhraseTraffic[1]
    Case "LOGIN" ; der Client loggt sich ein
    TCPSend($iClientSocket, "LOGIN_SUCCESS" & @CRLF & $sTCPLineBreak)
    GUISetState(@SW_SHOW, $hGUI)
    ConsoleWrite("CLIENT ONLINE!" & @CRLF)
    Case "EXIT" ; der Client geht offline
    TCPCloseSocket($iClientSocket)
    $iClientSocket = -1
    MsgBox(48, $sTitle, "Der Client hat die Verbindung zum Server geschlossen!", 0, $hGUI)
    Exit
    Case "REVC_SCREEN" ; wir empfangen den screen
    ConsoleWrite("Empfange Screenshot ... ")
    Local $fOpenScreen, $iTimeOut = TimerInit(), $sRevcMsg, $iCurrentByte = 0
    ; wir öffnen eine datei zum schreiben der daten
    $fOpenScreen = FileOpen(@ScriptDir & "\DOWNLOAD.jpg", 18)
    If @error Then Return -1
    ; wir schicken die bestätigung, dass es los gehen kann
    TCPSend($iClientSocket, "START_REVC" & @CRLF & $sTCPLineBreak)
    While 1 ; wir empfangen die daten
    $sRevcMsg = TCPRecv($iClientSocket, $iTCPMaxByte, 1)
    If $sRevcMsg <> "" Then $iTimeOut = TimerInit() ; timer für timeout setzen
    $iCurrentByte += BinaryLen($sRevcMsg) ; aufschreiben der empfangenen bytes
    FileWrite($fOpenScreen, $sRevcMsg) ; schreiben der daten
    If $sRevcMsg = "" And $iCurrentByte >= $aPhraseTraffic[2] - 50 Then ExitLoop ; wenn die empfangenden bytes >= der enddateigröße sind
    If TimerDiff($iTimeOut) > $iTCPTimeOut Then ; timeout abfragen
    FileClose($fOpenScreen)
    Return -1
    EndIf
    Sleep(15)
    WEnd
    FileClose($fOpenScreen) ; fertig mit dem empfangen und screen anzeigen
    GUICtrlSetImage($cScreen, @ScriptDir & "\DOWNLOAD.jpg")
    ConsoleWrite("FERTIG!" & @CRLF)
    EndSwitch
    EndFunc ;==>_PhraseGlobalTraffic

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

    Func _Global_Exit()
    ; wenn der Server sich beendet sagen wir den Clienten tschüss :)
    If $iClientSocket > 0 Then
    TCPSend($iClientSocket, "EXIT" & @CRLF & $sTCPLineBreak)
    TCPCloseSocket($iClientSocket)
    EndIf
    TCPShutdown()
    EndFunc ;==>_Global_Exit

    [/autoit]
    Client.au3
    [autoit]

    #include <ScreenCapture.au3>
    Opt("TCPTimeout", 100)
    OnAutoItExitRegister("_Global_Exit")
    ; durch das reduzieren der JPG Qualität wird die übertragung extrem beschleunigt
    _ScreenCapture_SetJPGQuality(75)
    TCPStartup()

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

    ; hier musst du die $iServerIP anpassen!
    Global $iServerPort = 12900, $sServerIP = "10.0.2.2", $iServerSocket = -1, _
    $sTCPLineBreak = "<START_NEXT_COMMAND>" & @CRLF, $iTCPMaxByte = 204800, $iTCPTimeOut = 3000

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

    $iServerSocket = TCPConnect($sServerIP, $iServerPort)
    If @error Then
    MsgBox(16, "ERROR", "Verbindung zum Server fehlgeschlagen!")
    Exit
    EndIf

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

    ; der Client versucht sich im Server einzuloggen
    ; => erfolgreich, wenn der Server noch einen platz frei hat
    Local $sRevcData, $sRevcDataSeg, $aSplitCommand, $iCommandStep, $iTimeOut = TimerInit()
    TCPSend($iServerSocket, "LOGIN" & @CRLF & $sTCPLineBreak)
    Do ; warten auf antwort...
    $sRevcData = TCPRecv($iServerSocket, $iTCPMaxByte)
    If TimerDiff($iTimeOut) > $iTCPTimeOut Then ExitLoop
    Until $sRevcData <> ""
    If Not StringInStr($sRevcData, "LOGIN_SUCCESS") Then
    MsgBox(16, "ERROR", "LOGIN Failed!")
    Exit
    EndIf

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

    ConsoleWrite("Erfolgreich mit Server verbunden!" & @CRLF)

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

    While Sleep(25)
    ; permamentes abfragen ob daten ankommen
    $sRevcData = TCPRecv($iServerSocket, $iTCPMaxByte)
    If $sRevcData <> "" Then
    Do
    $sRevcDataSeg = TCPRecv($iServerSocket, $iTCPMaxByte)
    If $sRevcDataSeg = "" Then ExitLoop
    $sRevcData &= $sRevcDataSeg
    Until $sRevcDataSeg <> ""

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

    ; falls mehrere Daten gleichzeitig ankommen splitten wir, damit keine Befehle untergehen
    $aSplitCommand = StringSplit($sRevcData, $sTCPLineBreak, 1)
    For $iCommandStep = 1 To $aSplitCommand[0]
    If $aSplitCommand[$iCommandStep] <> "" Then _PhraseGlobalTraffic($aSplitCommand[$iCommandStep])
    Next
    EndIf
    WEnd

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

    Func _PhraseGlobalTraffic($sPhraseTraffic)
    Local $aPhraseTraffic = StringSplit($sPhraseTraffic, @CRLF, 1)
    If @error Then Return -1
    Switch $aPhraseTraffic[1]
    Case "EXIT"
    TCPCloseSocket($iServerSocket)
    $iServerSocket = -1
    MsgBox(48, "ERROR", "Der Server hat die Verbindung geschlossen!")
    Exit
    Case "REFRESH_SCREEN" ; der server will einen screen
    Local $sRevcData, $fOpenScreen, $sScreenSize, $iTimeOut = TimerInit(), $sSendData
    ; screen erstellen und öffnen der datei
    _ScreenCapture_Capture(@ScriptDir & "\screen.jpg")
    $fOpenScreen = FileOpen(@ScriptDir & "\screen.jpg", 16)
    If @error Then Return -1
    ; größe der datei abfragen
    $sScreenSize = FileGetSize(@ScriptDir & "\screen.jpg")
    ; server soll sich vorberreiten
    TCPSend($iServerSocket, "REVC_SCREEN" & @CRLF & $sScreenSize & @CRLF & $sTCPLineBreak)
    ConsoleWrite("Warte auf Screen bestätigung ... ")
    Do ; wir warten, dass der server so weit ist den screen zu empfangen
    $sRevcData = TCPRecv($iServerSocket, $iTCPMaxByte)
    If TimerDiff($iTimeOut) > $iTCPTimeOut Then
    FileClose($fOpenScreen)
    Return -1
    EndIf
    Sleep(25)
    Until StringInStr($sRevcData, "START_REVC")
    ConsoleWrite("BESTÄTIGT! " & @TAB & "Sende ... ")
    Do ; wir senden den Screen
    $sSendData = FileRead($fOpenScreen, $iTCPMaxByte)
    If @error Then ExitLoop
    TCPSend($iServerSocket, $sSendData)
    Sleep(10)
    Until $sSendData = ""
    FileClose($fOpenScreen) ; fertig :)
    ConsoleWrite("FERTIG!" & @CRLF)
    EndSwitch
    EndFunc ;==>_PhraseGlobalTraffic

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

    Func _Global_Exit()
    ; wenn der Client sich beendet loggen wir uns am server aus
    If $iServerSocket > 0 Then
    TCPSend($iServerSocket, "EXIT" & @CRLF & $sTCPLineBreak)
    TCPCloseSocket($iServerSocket)
    EndIf
    TCPShutdown()
    EndFunc ;==>_Global_Exit

    [/autoit]


    ich hoffe es ist angemessen kommentiert

    ja, wie halt gesagt, TCP macht es einem nicht ganz so einfach
    und was mir einfällt, ich habe jetzt keine prüfung drinn, ob die server verbindung noch existiert, weil wenn die abschmiert läuft es weiter ohne dass was passiert^^
    die kannst du ja mal versuchen einzubauen als übung oder so dazu brauchst du nur einen Timer der alle X sekunden eine nachricht in der mainloop an die verbindung sendet und da kannst du dann @error abfragen :)

    mfg

  • ich hab erst seit paar wochen mit autoit angefangen und deswegen mache ich noch einige fehler aber danke für die schnelle antwort es funktioniert sehr gut!