Bildschirmübertragung - Remote Desktop

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von 13.1.24.

    Bildschirmübertragung - Remote Desktop

    Hallo,
    als allererstes: Ich bin neu im Forum und wünsche allen erstmal einen schönen guten Tag. :)
    Ich schreibe gerade eine (eig. zwei) Anwendungen für eine Remote Desktop Übertragung.
    Der Code, den ich verwende, sieht bisher so aus:

    Client:

    Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Imports System.Threading
    4. Public Class Form1
    5. Dim client As TcpClient
    6. Dim bwriter As BinaryWriter
    7. Dim breader As BinaryReader
    8. Dim IPAddress As String = "127.0.0.1"
    9. Dim Port As Integer = 1338
    10. Dim Frage As String
    11. Dim Antwort As String
    12. Sub Start()
    13. Dim t As New Thread(AddressOf Verbinden)
    14. t.IsBackground = True
    15. t.Start()
    16. End Sub
    17. Sub Verbinden()
    18. Try
    19. client = New TcpClient
    20. client.Connect(IPAddress, Port)
    21. If client.Connected = True Then
    22. bwriter = New BinaryWriter(client.GetStream)
    23. breader = New BinaryReader(client.GetStream)
    24. Dim t As New Thread(AddressOf Screen)
    25. t.IsBackground = True
    26. t.Start()
    27. End If
    28. Catch ex As Exception
    29. End Try
    30. End Sub
    31. Sub Screen()
    32. Try
    33. While client.Connected = True
    34. Dim b() As Byte = Image2ByteArray(Screenshot, Imaging.ImageFormat.Jpeg)
    35. bwriter.Write(CInt(b.Length))
    36. bwriter.Write(b)
    37. Thread.Sleep(100)
    38. End While
    39. Catch ex As Exception
    40. End Try
    41. End Sub
    42. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    43. End Sub
    44. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    45. Start()
    46. End Sub
    47. Public Function Screenshot()
    48. Dim Pic As New Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height)
    49. Dim graphic As Graphics = Graphics.FromImage(Pic)
    50. graphic.CopyFromScreen(0, 0, 0, 0, Pic.Size)
    51. graphic.Dispose()
    52. Return Pic
    53. End Function
    54. Public Function Image2ByteArray(ByVal Bild As Image, ByVal Bildformat As System.Drawing.Imaging.ImageFormat) As Byte()
    55. Dim MS As New IO.MemoryStream
    56. Bild.Save(MS, Bildformat)
    57. MS.Flush()
    58. Return MS.ToArray
    59. End Function


    Server:

    Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Imports System.Threading
    4. Public Class Form1
    5. Dim server As TcpListener
    6. Dim client As TcpClient
    7. Dim bwriter As BinaryWriter
    8. Dim breader As BinaryReader
    9. Dim Port As Integer = 1338
    10. Sub Start()
    11. Try
    12. server = New TcpListener(New System.Net.IPAddress(0), Port)
    13. server.Start()
    14. client = server.AcceptTcpClient
    15. bwriter = New BinaryWriter(client.GetStream)
    16. breader = New BinaryReader(client.GetStream)
    17. Dim t As New Thread(AddressOf ÜbertrageScreen)
    18. t.IsBackground = True
    19. t.Start()
    20. Catch ex As Exception
    21. End Try
    22. End Sub
    23. Sub ÜbertrageScreen()
    24. While True
    25. While client.Connected = True
    26. Try
    27. Dim l As Int32 = breader.ReadInt32
    28. Dim b() As Byte
    29. b = breader.ReadBytes(l)
    30. PictureBox1.Image = ByteArray2Image(b)
    31. Catch ex As Exception
    32. End Try
    33. End While
    34. End While
    35. End Sub
    36. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    37. Dim main As New Thread(AddressOf Start)
    38. main.IsBackground = True
    39. main.Start()
    40. End Sub
    41. Public Function ByteArray2Image(ByVal ByAr() As Byte) As Image
    42. Dim img As Image
    43. Dim MS As New IO.MemoryStream(ByAr)
    44. 'das TRY ist Notwending, da wenn ein ARRAY eingelesen wird, welches KEIN Bild war,
    45. 'eine Exception auftritt!
    46. Try
    47. img = Image.FromStream(MS)
    48. Catch ex As Exception
    49. Return Nothing
    50. End Try
    51. Return img
    52. End Function
    53. End Class


    Ist mehr oder weniger provisorisch. Funktioniert aber schon einwandfrei.
    Jetzt, möchte ich die Serverfunktion in eine Extra Class auslagern und das Bild dann in die PictureBox1 laden.
    Und genau da liegt das Problem...
    Lagere ich die Annahme des Arrays (breader.Read) + die Umwandlung des Arrays ins Image (ByteArray2Image) in eine andere Klasse aus
    und übergebe dann die Variable Image (also das umgewandelte Bild) der Form, bekomme ich kein Bild.
    Hab's mehrmals überprüft: sowohl die Länge des Arrays (l) als auch die Bytes (b) kommen an, das Array wird in ein Image umgewandelt, aber nach wie vor
    bekomme ich kein Bild zu sehen. Wie gesagt, wenn ich es so mache wie oben beschrieben, funktioniert es einwandfrei. Beim Auslagern in eine Class nicht.
    Hoffe, dass mir hier vielleicht jemand helfen kann. :)
    LG
    Das wird spätestens nich funktionieren wenn du das ausserhalb vom internen Netzwerk nutzen willst (also über die globale IP),
    weil du 1. TCP nutzt (das zu langsam weil du viele Daten in kurzer Zeit schicken musst)
    und 2. das Bild als ganzes sendest (sind zuviele Bytes)

    Hab selber mal sowas versucht mit UDP nach folgendem Schema:

    1. Das Bild umwandeln in Bytes
    2. Bytes komprimieren
    3. Bytes einteilen in x Teilbytefolgen (dann in das Array z.B. an der ersten Position die Nummer des Pakets reinschreiben, weil mit UDP können die Pakete in der falschen Reihe ankommen (muss du dann serverside synchronisieren))
    Falls erstes Bild:
    4. Alle Teilbytefolgen senden
    sonst:
    4. Prüfen ob sich eine der Teilbytefolgen von eine der Teilbytefolgen des letzten Bildes unterscheidet -> falls ja senden

    Dann musst du die Pakete beim Gegenüber in die richtige Reihenfolge anordnen und dementsprechend anzeigen

    Hatte dabei Probleme mit "4. Prüfen ob sich eine der Teilbytefolgen von eine der Teilbytefolgen des letzten Bildes unterscheidet -> falls ja senden"
    vermutlich muss man das so machen, dass man bevor man das komprimiert vergleichen muss ob die sich unterscheiden und nicht nachher (weil nach dem komprimieren die Länge des Byte-arrays sich jenach bild unterscheidet)

    Nur so als kleiner Tipp, falls du vorhast das ganze Internetübergreifend zu nutzen.
    Willkommen im Forum. :thumbup:

    13.1.24 schrieb:

    Remote Desktop Übertragung
    Braucht das irgend jemand oder willst Du Dich nur das Thema einarbeiten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dankeschön als Erstes für die Beiträge.
    @RushDen
    Das ist nicht das Problem. Die gepostete Version funktioniert über die globale IP.
    Das Problem ist, dass das Bild, wenn ich es von einer Class (mittels eines Events, o.ä.) an die Form weiter gebe, nicht erscheint.
    Ich kann sowohl die Länge des Arrays als auch das Array selbst auslesen (was ja quasi die Bestätigung einer Datenübertragung ist).
    @RodFromGermany
    Will mich nur einarbeiten. ;)
    Wenn das wirklich funktioniert hast du ne 100k Leitung und lässt das ganze auf 20-30 FPS laufen? (edit auf 10 FPS, nagut)

    (Ja bei TCP wird das sichergestellt dass die Daten ankommen, aber nach einiger Zeit wird dein Internet die Last nicht aushalten und das ganze wird extrem verzögert ankommen, also dass du das Array auslesen kannst ist kein Indiz dafür dass es funktioniert.)

    Ahja um dein Problem zu lösen:

    Hau mal das Try catch raus, dann kriegste eine Exeption die dir sagt dass du Invoken sollst (d.h. die Image der Picturebox im Mainthread (da wo Sie erstellt worden ist) zu ändern und nicht im Nebenthread wo du nach den Daten lauscht))

    Das mit der 100k Leitung stimmt tatsächlich. :D
    Wie dem auch sei: Was ich eig. meinte war, dass das Bytearray (das Array des Bildes) ja beim Server ankommt. Somit kann es also (in der Theorie) NICHT an der Verbindung
    liegen, dass ich kein Bild habe (da das Array ja ankommt). Das Array wird ja außerdem erst vor dem Laden in die PictureBox1 mittels ByteArray2Image in ein Bild umgewandelt.
    Pardon, das hab ich glatt übersehen.....hilft mir jedoch auch nicht.
    Im geposteten Code funktioniert alles weiterhin einwandfrei, lagere ich das alles in eine Class aus und lade es das übertragene "Image" in eine PictureBox einer Form (mit Invoke)
    funktioniert es immernoch nicht.
    Lad maln Sample hoch, weil

    VB.NET-Quellcode

    1. Sub ÜbertrageScreen()
    2. While True
    3. While client.Connected = True
    4. Try
    5. Dim l As Int32 = breader.ReadInt32
    6. Dim b() As Byte
    7. b = breader.ReadBytes(l)
    8. PictureBox1.Image = ByteArray2Image(b)
    9. Catch ex As Exception
    10. End Try
    11. End While
    12. End While
    13. End Sub


    und

    VB.NET-Quellcode

    1. Dim t As New Thread(AddressOf ÜbertrageScreen)
    2. t.IsBackground = True
    3. t.Start()


    wird sicher nicht ohne Exception funktionieren (das Try catch weg !)


    edit: Im Anhang hab Ich auch das Projekt von mir, wenn du das mal sehen willst (war ein Testprojekt und hab das mit dem vergleichen nicht drinne), da wird das Bild in x Teilbilder aufgeteilt (10) und beim Empfänger wieder zusammengesetzt und läuft mit UDP - kannst du mal ausprobieren. (Sind keine binaries, musst du selbst kompilieren).

    Musst zweimal das Programm starten
    dann auf 2 verschiedene Ports binden
    Anschliessend bei einem auf Start Receive drücken
    und bei dem anderen die IP Adresse (127.0.0.1) und den Port des anderen eingeben und die Checkbox enablen
    Dateien
    • RemoteClient.zip

      (43,2 kB, 153 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „RushDen“ ()

    Ich hab's jetzt nochmals in einem komplett neuen Projekt ausprobiert.
    Dort klappt es komischerweise...
    Ich muss irgendwas übersehen haben. Wenn ich rausfinde was es war, kann ich es ja eventuell nochmal posten.

    @RushDen:
    Danke für den Anhang. Werd ich mir mal anschauen/ausprobieren. Sieht nach 'ner resourcenfreundlicheren/besseren Lösung aus. :)
    Danke auch für die Hilfe! :)