Bild wird nicht richtig übertragen!

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    Bild wird nicht richtig übertragen!

    Guten Abend/Morgen liebe VBler!
    Ich habe mir einen Server und einen Clienten geschrieben, zwischen denen Bilder ausgetauscht werden sollen. Doch leider kommen die Bilder nicht ordnungsgemäß beim Server an.
    Wieso weiß ich leider nicht, deswegen frage ich nun euch!

    Hier ist mein Code:

    Server

    VB.NET-Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Imports System.Threading
    4. Imports System.Net
    5. Public Class Form1
    6. Dim stream As NetworkStream
    7. Dim streamr As BinaryReader
    8. Dim Server As TcpListener
    9. Dim client As New TcpClient
    10. Dim ipendpoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8000)
    11. Dim mainthread As Threading.Thread
    12. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    13. mainthread = New Threading.Thread(AddressOf mainserver)
    14. mainthread.Start()
    15. End Sub
    16. Sub mainserver()
    17. Try
    18. Server = New TcpListener(ipendpoint)
    19. Server.Start()
    20. client = Server.AcceptTcpClient
    21. stream = client.GetStream
    22. streamr = New BinaryReader(stream)
    23. Dim pictureBuffer(client.ReceiveBufferSize) As Byte
    24. streamr.Read(pictureBuffer, 0, client.ReceiveBufferSize)
    25. Dim buffer As New MemoryStream(pictureBuffer)
    26. PictureBox1.Image = Image.FromStream(buffer)
    27. Catch ex As Exception
    28. MsgBox(ex.Message)
    29. End Try
    30. End Sub
    31. End Class


    Client

    VB.NET-Quellcode

    1. Imports System.Net.Sockets, System.IO
    2. Public Class Form1
    3. Dim Client As New TcpClient 'Client
    4. Dim stream As NetworkStream
    5. Dim streamw As BinaryWriter
    6. Dim streamr As BinaryReader
    7. Sub verbinde_zu_server()
    8. Client.Connect("127.0.0.1", 8000)
    9. If Client.Connected Then
    10. stream = Client.GetStream
    11. streamw = New BinaryWriter(stream)
    12. streamr = New BinaryReader(stream)
    13. Else
    14. MsgBox("Fehler!")
    15. End If
    16. End Sub
    17. Sub sende()
    18. Dim buffer() As Byte
    19. Dim ofd As New OpenFileDialog
    20. If ofd.ShowDialog() = DialogResult.OK Then
    21. buffer = File.ReadAllBytes(ofd.FileName)
    22. streamw.Write(buffer)
    23. End If
    24. End Sub
    25. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    26. sende()
    27. End Sub
    28. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    29. verbinde_zu_server()
    30. End Sub
    31. End Class


    Der Fehler (siehe Anhang) tritt nur auf, wenn ich ein Bild von einem Rechner aus sende. Also über das Internet!


    dER fEHL

    Bilder
    • Bild.jpg

      547,58 kB, 1.912×777, 157 mal angesehen
    Wo viel kopiert wird, wird wenig kapiert.
    Andreas Tenzer
    (Dt. Philosoph, * 1954)

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

    die buffergröße ist begrenzt, die Daten kommen deshalb nur stückchenweiße an, deshalb ist ReceivedBufferSize kleiner als die tatsächlich größe des Bildes, deshalb benötigst du etwas wie ein einfaches Protokoll, welches der gegenseite die größe der zu empfangenden Daten mitteilt. Mit einem BinaryReader/Writer kann man z.b. ganz einfach ints versenden(nur 4 byte)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Wenn ich das richtig verstanden habe, dann würde folgendes reichen?
    Ich übertrage die tatsächliche Größe des zu sendenden Bildes bevor ich das Bild sende, d.h ich werde einen Integer nehmen und dem die Größe des Bildes zuweisen.
    Diesen Integer werde ich an den Server senden und der nimmt diesen Integerwert und setzt diesen als Größe des zu empfangenen Streams. Also anstelle ReceivedBufferSize,
    da ReceivedBufferSize nur die Größe eines Stückchens enhält?
    Wo viel kopiert wird, wird wenig kapiert.
    Andreas Tenzer
    (Dt. Philosoph, * 1954)
    Oder was du auch machen kannst, ist es mit
    Image img = new Bitmap(pfad) und dann mit Bitmap.Save(Stream, ImageFormat) (Von Image geerbt in einen NetworkStream schreiben.

    Senden:

    C#-Quellcode

    1. Image img = new Bitmap("C:\\bild.jpg");
    2. using (NetworkStream ns = client.GetStream())
    3. {
    4. img.Save(ns, System.Drawing.Imaging.ImageFormat.Jpeg);
    5. }


    Empfangen:

    C#-Quellcode

    1. Image img;
    2. using (NetworkStream ns = new NetworkStream(client))
    3. {
    4. img = new Bitmap(ns);
    5. }
    6. img.Save("C:\\bild_gesendet.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);


    Musste halt noch in Vb übersetzen
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Hm...

    Also, das Ganze hat dann für das "Problembild" funltioniert. Jetzt hatte ich mir nochmals Gedanken gemacht und habe ein Bild mit der Größe von "2,141 MB" versucht zu versenden.
    Das Resultat könnt ihr im Anhang sehen :( Wieso will das nicht?

    Eine 10 MB große .7z Datei kann ich nach Übertragung auch nicht mehr öffnen :/
    Bilder
    • Forum.JPG

      337,72 kB, 1.467×485, 105 mal angesehen
    Wo viel kopiert wird, wird wenig kapiert.
    Andreas Tenzer
    (Dt. Philosoph, * 1954)
    Wie lautet denn der zugehörige Code?

    Du musst außerdem natürlich so viele Bytes lesen, bis alle Bildbytes angekommen sind.

    VB.NET-Quellcode

    1. Dim buffer(imageBytes - 1) As Byte
    2. Dim ci As Integer = 0
    3. While ci < imageBytes
    4. ci += stream.Read(buffer, ci, imageBytes - ci)
    5. 'hier ggf. warten oder irgendwas machen
    6. End While


    Viele Grüße
    ~blaze~

    VB.NET-Quellcode

    1. Dim laenge As Int32 'Variable um die Dateigröße zu speichern und zu senden'
    2. Server = New TcpListener(ipendpoint) 'Server initialisieren'
    3. Server.Start() 'Server starten'
    4. Do
    5. client = Server.AcceptTcpClient 'Clienten aktzeptieren'
    6. stream = client.GetStream 'Stream des Clienten dem Server zuweisen'
    7. streamr = New BinaryReader(stream) 'Stream für Bytes der zu empfangenen Datei'
    8. groesse = New BinaryReader(stream) 'Stream für Empfang der Größe der Datei'
    9. laenge = groesse.ReadInt32 'Die Größer der Datei in der Variablen speichern'
    10. Dim pictureBuffer(laenge - 1) As Byte 'Byte-Array deklarieren, mit der Größe der Datei'
    11. streamr.Read(pictureBuffer, 0, laenge) 'Byte-Array mit den Bytes der empfangenen Datei füllen'
    12. File.WriteAllBytes(My.Computer.FileSystem.SpecialDirectories.Desktop & "\test.jpg", pictureBuffer) 'Bild auf Desktop abspeichern'
    13. Loop


    Das wäre mein Code. Für kleinere Dateien funktioniert der Code wunderbar.

    EDIT:// blaze, dein Code hat funktioniert! Vielen Dank erstmals dafür! Nur reicht es mir nicht, ich möchte gerne nachvollziehen können, wieso meiner nicht funktioniert. Kannst du mir das vielleicht sagen? Ich komme einfach nicht drauf.

    EDIT:// Gehört vielleicht nicht zum Threadtitel, aber ich kann nicht zwei mal hintereinander ein Bild wählen und senden. Nur wenn ich den Clienten einmal schließe und wieder starte, dann kann ich wieder ein Bild senden. Woran könnte das denn liegen? (ERLEDIGT)
    Wo viel kopiert wird, wird wenig kapiert.
    Andreas Tenzer
    (Dt. Philosoph, * 1954)

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „F4talError“ ()

    Hey.

    1. Wieso verwendest du 2 BinaryReader?
    Du hast einen Stream. Nimm einen Reader. Lies die Länge zuerst aus und dann erst den Rest.
    2.In deinem Code kannst du dir ja mal anschauen, was

    VB.NET-Quellcode

    1. streamr.Read(pictureBuffer, 0, laenge) 'Byte-Array mit den Bytes der empfangenen Datei füllen'


    für einen Returnwert hat, bei dem Bild, was nicht vollständig übertragen wurde.
    Der Returnwert gibt die Anzahl der gelesenen Bytes zurück.
    Das ist meine Signatur und sie wird wunderbar sein!
    @F4talError Vielleicht konvertierst Du Dein Bild zur Übertragung in einen Base64-String und nach der Übertragung wieder zurück, da kannst Du während der Übertragung mit ganz normalen Steuerzeichen arbeiten, gugst Du hier.
    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!
    @RushDen das geht bei einem binären Datenstrom nicht, da dieser bereits beliebige zeichen und somit auch dein Steuerzeichen beinhalten könnten, dann müsstest du alle zeichen im binären Datenstrom escapen, was nochmal ein Arbeitsgang ist, oder eben etwas wie Base64, was @~blaze~ bereits angemerkt hat eine Platzverschwendung ist.
    Vorallem find ich das binäre senden sogar einfacher, zwar nicht so leicht zu debuggen in manchen Situationen, aber ansonsten weniger zu beachten.
    @F4talError es gibt auch BinaryReader.ReadBytes(count)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---