Toon posts:

vb.net bestand doorsturen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Geachte,

Ik ben al een tijdje bezig in vb.net en probeer nu een bestand door te sturen van client naar server
Momenteel heb ik de volgende code:
Visual Basic: Client - (functie om van bestand naar byte array te gaan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    Private Function ReadFile(ByVal filePath As String) As Byte()
        Dim oFile As System.IO.FileInfo
        oFile = New System.IO.FileInfo(filePath)

        Dim oFileStream As System.IO.FileStream = oFile.OpenRead()
        Dim lBytes As Long = oFileStream.Length
        Dim fileData(lBytes - 1) As Byte

        If (lBytes > 0) Then
            oFileStream.Read(fileData, 0, lBytes)
            oFileStream.Close()
        End If
        Return fileData
    End Function


Visual Basic: Client - (functie om van byte array door te sturen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Private Sub Send()
        Dim sw As IO.StreamWriter
        Dim arr() As Byte = ReadFile("test.bmp")
        Try
            sw = New IO.StreamWriter(tcpClient.GetStream)
            sw.Write("filesending:" & arr.Length)
            sw.Flush()
            For i As Integer = arr.Length - 2000 To arr.Length - 1
                veld_ontvangen.AppendText(arr(i) & vbCrLf)
                sw.Write(arr(i) & "-")
                sw.Flush()
            Next

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

Momenteel verstuur ik enkel de laatste 2000 bytes, (veld_ontvangen) is gewoon een txtveld waar ik de gegevens nog eens in toon


Visual Basic: Server- (functie om data te ontvangen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 Private Sub lees(ByVal ar As System.IAsyncResult)
        Dim totalRead As Integer
        Try
            totalRead = mClient.GetStream.EndRead(ar)
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
        If totalRead > 0 Then
            Dim receivedString1 As String = System.Text.Encoding.UTF8.GetString(readBuffer, 0, totalRead)


            If receivedString1.StartsWith("filesending:") Then
                Dim split() As String = receivedString1.Split(":")
                aantal = split(1)
                MessageBox.Show(aantal)
            ElseIf d.Count - 1 = aantal Then
                MessageBox.Show("einde")
                vormfile()
            Else
                Try
                    Dim splitt() As String = receivedString1.Split("-")
                    For i As Integer = 0 To splitt.Length - 1
                        If Len(splitt(i).ToString) <> 0 Then
                            d.Add(splitt(i))
                            Console.WriteLine(splitt(i) & " - " & Len(splitt(i).ToString))
                        End If

                    Next
                Catch ex As Exception
                    MessageBox.Show(ex.ToString & " de ERROR")
                End Try
            End If
        End If
        Try
            mClient.GetStream.BeginRead(readBuffer, 0, BYTES_TO_READ, AddressOf lees, Nothing)
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

d is een arraylist, de data wordt van de client gestuurd onder de vorm 55-66-8-51-103-58, vandaar dat ik split op (-) om de bytes te kunnen onderscheiden.
Nu controleer ik ook op lege bytes en deze laat hij ervan tussen, alleen als ik nu laat printen hoeveel plaatsen er gevuld zijn in d krijg ik de waarde 2005, terwijl er maar 2000 zijn verzonden.
als ik de arraylist laat printen zie ik dat er 3 lege plaatsen zijn:
- kan er niet bijkomen hoe dit kan
- dan zit ik nog altijd met 2 bytes teveel
Een 2de probleem is dat de byte array in de client soms groter of kleiner is, orde +-20 bytes

Vandaar dan ook men vraag Hoe kan dit? en nog belangrijker is dit een omslachtige manier van werken of bestaat er al een class die dit werk al doet?

Alvast bedankt
Kristof

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Gebruik alsjeblieft een bestaand protocol in plaats van zelf een te schrijven. Het is bij de gratie Gods dat het tot nog toe werkt. Als ik het goed lees, stuur je dit als je de string "ABC" wil versturen, het volgende:
code:
1
filesending:365-66-67-

Dat de Flush() werkt is leuk, maar dat het is niet gegarandeerd dat de data op die manier en op dat moment aankomt. Zeker niet als je netwerk, server of client wat drukker is. Het kan best dat de data dan als volgt wordt ontvangen:
code:
1
file
code:
1
sending:
code:
1
3
code:
1
65-66-67-

Want EndRead kan al returnen als er één byte is ontvangen. Doet jouw programma dan nog wat als je bovenstaande data in losse brokken ontvangt? En wat zijn lege bytes? En waarom ga je een byte tot wel vier keer opblazen om hem te versturen?

Je zou gebruik kunnen maken van een separator (een crlf bijvoorbeeld, maar daar dan alleen op controleren bij de header(s)) en de binaire data as-is versturen. Of je poept de file gewoon één op één uit, zonder headers, en sluit de verbinding vanaf de client als het verzenden klaar is. Als de verbinding te vroeg verbroken wordt, wordt er toch een exception gegooid (bij een netjes gesloten socket geeft EndRead een 0 terug, anders een exception).

Je zou ook, de overkill daargelaten, WCF kunnen misbruiken zoals hier. Of je pakt een HTTP-client en -server.


Maar, ontopic: als je uitvoer niet gelijk is aan je invoer, dan vergelijk je die twee toch? Bijvoorbeeld in Notepad++ met de diff viewer. Want als je wil dat wij jouw probleem kunnen reproduceren, dan moeten we nu de code overnemen (of aandachtig doorlezen) en zorgen dat we dezelfde input hebben als jij (want misschien gaat het met een andere bmp-file wel weer perfect).

Isoleer eerst de oorzaak van het probleem zelf, en waarschijnlijk zie je dan direct ook de oplossing.

[ Voor 14% gewijzigd door CodeCaster op 01-08-2011 14:25 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 10-10 12:54
Verwijderd schreef op maandag 01 augustus 2011 @ 13:50:
bestaat er al een class die dit werk al doet?
Jahoor :) (zie 'Examples')

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de reacties,

Mijn code eens wat opgekuist en nu werk ik met een binaryReader en Writer i.p.v. een streamR/W. Dit maakte alles veel gemakkelijker en ondertussen heb ik dit werkend.

Echter heb ik toch nog een vraagje i.v.m. de flush(). Als dit een niet betrouwbare functie is, wat kan men er dan voor in de plaats gebruiken?

Kristof

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Flush is hartstikke betrouwbaar, hij doet precies wat in de documentatie staat. Wat jouw probleem echter is, is dat je niet kan garanderen dat de andere kant pas op dat moment stopt met lezen. Er kan best één byte binnenkomen, of vier. En dan heb jij nog niet genoeg data om je 'protocol' te laten functioneren. Je hebt dus iets nodig als een separator, een uniek(e) teken(reeks) wat/die jouw client of server laat weten dat een bepaalde hoeveelheid data die benodigd is voor de verwerking is ontvangen.

Ik weet zo snel niet of een Flush ook genegeerd kan worden om wat voor reden dan ook, dus dat er ná de in mijn voorbeeld gebruikte "filesending:3" doodleuk nog meer nummers gestuurd kunnen worden waardoor je server denkt dat er veel meer bytes dan 3 aankomen.

Het HTTP-protocol gebruikt hier bijvoorbeeld crlf's voor. Iedere regel is één header, één 'commando', en een regel wordt afgesloten met een crlf. Als jij dus afspreekt (in je protocol, in je code) dat de server wacht op de tekst "filesending:<(on)beperkt aantal cijfers><crlf>", dan maakt het niet uit dat die tekenreeks bij wijze van spreken bit voor bit binnenkomt, pas na de <crlf> ga je kijken wat je hebt ontvangen en of je hier chocola van kunt maken.

[ Voor 16% gewijzigd door CodeCaster op 01-08-2011 23:30 ]

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor de extra informatie, ik zal me hier wat meer moeten in verdiepen.

Nu heb ik nog een klein vraagje, het staat niet echt i.f.v. dit topic maar om een nieuw topic hiervoor te openen leek het mij niet echt zinvol.
Dim verbonden_client As New verbondenclient(Incomming, Me)

Hier maak ik een object aan per user dat connectie maakt met de server en geef ik wat parameters mee, nu per object heb ik apparte threats zodat het server prog beschikbaar blijft voor inputs van de gebruiker. Alleen hoe sluit ik deze? Hiermee bedoel ik dan: als een user uitlogt hoe verwijder ik dan verbonden_client? zodat deze geen geheugen meer inneemt. Google geeft mij vaak weer Dispose/Remove aleen kan ik niet vinden hoe ik deze kan laten werken.

Alvast bedankt
Kristof

[ Voor 6% gewijzigd door Verwijderd op 03-08-2011 15:40 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Verwijderd schreef op woensdag 03 augustus 2011 @ 15:38:
Google geeft mij vaak weer Dispose/Remove aleen kan ik niet vinden hoe ik deze kan laten werken.
Doe eens gek en lees de documentatie :?
MSDN: IDisposable.Dispose Method (System)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1