Avatar billede tetrix Nybegynder
16. oktober 2010 - 23:04 Der er 27 kommentarer og
1 løsning

Vedvarende stream

Hej.

Er ved at lave noget ala. Remote Desktop i Visual Basic. Hver gang et nyt screen requestes åbnes en ny forbindelse. Det virker fint, men jeg ved gerne overføre i en vedvarende forbindelse, altså uden at skulle starte en ny.

Med andre ord vil jeg gerne signalere hvornår EOF forekommer, så modtageren kan modtage endnu en gang.

Her er hvad jeg har gjort indtil videre.

På senderens side:
- Gem et screenshot i en MemoryStream
- Overfør billedet
- Send et signal for EOF, her er hvad jeg har gjort pt.
ns.Write(BitConverter.GetBytes(-1), 0, 4)
ns.Flush()


Modtageren tjekker så for EOF ved at tjekke om BitConverter.ToInt32(b, 0) = -1.

Det hele virker faktisk fint nok, men mit EOF-signalement når ikke altid frem til modtageren uden noget andet, hvilket resulterer i at der går yderligere tid.

Hvad skal jeg gøre for at signalere EOF, uden at lukke forbindelsen?

Tak.
Avatar billede arne_v Ekspert
17. oktober 2010 - 02:03 #1
Send:

4 bytes med længden N
N bytes med data

og lad modtagerr først læse N og derefter N bytes.
Avatar billede tetrix Nybegynder
17. oktober 2010 - 12:34 #2
Har nogenlunde gjort det, men der var et problem.

Første gang læste den længden, 1025, anden gang var længden meget høj og der opstod en exception. Har det noget med min java middle-man server at gøre, eller noget med buffersize? Alle buffer sizes er 1024, men den forsøger alligevel at sende en længde på 1025.
Avatar billede arne_v Ekspert
17. oktober 2010 - 15:29 #3
Det lydere snarere som en simpel kdoe fejl.

Sender du 1024 skal der læses 1024 og læses 1024 bytes.

Prøv og vis noget kode.
Avatar billede tetrix Nybegynder
17. oktober 2010 - 16:04 #4
Det virker nu, meget underligt.

Før gjorde jeg sådan her.
dim b(1024) as byte
stream.read(b, 0, b.Length)


Ændrede det til..
dim b(1024) as byte
stream.read(b, 0, 1024)


.. og det løste problemet. Er der en forklaring på dette eller jeg har gjort noget andet?

Smid desuden lige et svar, takker.
Avatar billede arne_v Ekspert
17. oktober 2010 - 16:46 #5
Jeg gætter på at:

dim b(1023) as byte
stream.read(b, 0, b.Length)

også virker!

a(n) er 0..n altså n+1 elementer
Avatar billede arne_v Ekspert
17. oktober 2010 - 16:46 #6
og et svar
Avatar billede tetrix Nybegynder
17. oktober 2010 - 17:22 #7
Endnu et problem.

Løsningen virker på localhost men ikke fra en anden LAN eller WAN forbindelse. Hvad kan dette skyldes?
Avatar billede arne_v Ekspert
17. oktober 2010 - 17:28 #8
Firewall?
Avatar billede tetrix Nybegynder
17. oktober 2010 - 17:37 #9
Nope, det er igen den forkerte længde der læses. Læses rigtigt et par gange, derefter et resultat som -123949123.
Avatar billede arne_v Ekspert
17. oktober 2010 - 17:47 #10
Sender skal kalde Flush når en "portion" er færdig skrevet.

Modtager skal:
- læse 4 bytes med længden N
- læse N byte i en while løkke (fordi de N bytes kan godt kræve mere end 1 read)
Avatar billede tetrix Nybegynder
17. oktober 2010 - 17:58 #11
Vil tro at det er det jeg gør, du får lige kode.

Modtager:

                            Dim n As Integer = s.Read(b, 0, 1024)
                            While (n > 0)
                                Dim j As Integer = BitConverter.ToInt32(b, 0)
                                If (j = -1) Then
                                    'signalerer EOF
                                Else
                                    mmStream.Write(b, 4, j)
                    'her opstår fejl eftr et par gange.
                                End If
                                n = s.Read(b, 0, 1024)
                            End While


Sender:
                            Dim readByte(1020 - 1) As Byte, n As Integer = ms.Read(readByte, 0, readByte.Length)
                            While (n > 0)
                                Dim sendByte(1024 - 1) As Byte
                                Array.Copy(BitConverter.GetBytes(n), 0, sendByte, 0, 4)
                                Array.Copy(readByte, 0, sendByte, 4, n)
                                'send
                                bins.Write(sendByte, 0, sendByte.Length)
                                bins.Flush()
                                'read next
                                n = ms.Read(readByte, 0, readByte.Length)
                            End While
                            ms.Close()
                            Dim endByte(1024) As Byte
                            Array.Copy(BitConverter.GetBytes(-1), 0, endByte, 0, BitConverter.GetBytes(-1).Length)
                            'send endByte
                            bins.Write(endByte, 0, 1024)
                            bins.Flush()
Avatar billede arne_v Ekspert
17. oktober 2010 - 18:19 #12
Den kode tror jeg kan forbedres meget.

**** utestet ****

sender
------

Du skal sende sendByte til bins:

bins.Write(BitConverter.GetBytes(sendByte.Length), 0, 4)
bins.Write(sendByte, 0, sendByte.Length)
bins.Flush

modtager:

Dim bn(4-1) As Byte
s.Read(bn, 0, 4)
Dim n As Integer = BitConverter.GetInt32(bn, 0, 4)
Dim b() As Byte = New Byte(n)
Dim ix As Integer = 0
Dim tmp As Integer
While (tmp = s.Read(b, ix, b.Length - ix) > 0
    ix = ix + tmp;
End While
Avatar billede tetrix Nybegynder
17. oktober 2010 - 19:14 #13
Forstår sender delen, men hvor skal den nye modtagerdel placeres?
Avatar billede tetrix Nybegynder
17. oktober 2010 - 19:25 #14
Det skal siges at længden af et chunk sendes med hvert chunk. Det overstående eksempel kunne godt ligne et eksempel på en længde af det hele der sendes først, men det skal jeg ikke kunne sige.
Avatar billede arne_v Ekspert
17. oktober 2010 - 19:55 #15
Ja.

Det sender en total længde.

Medmindre der er noget magisk ved chunks så kan det ikke betale sig at chunke.

Fordi hvis du sender 3 chunks af 1000, 1000 og 700 bytes så kan modtager læse dem som 800, 750, 750 og 400 bytes.
Avatar billede tetrix Nybegynder
17. oktober 2010 - 20:02 #16
Så bør jeg gøre således?

Client:
1) Send total size
2) Overfør
3) Repeat

Server:
1) Modtag total size
2) Modtag, indtil størrelsen på modtaget bytes >= total size
3) Repeat
Avatar billede arne_v Ekspert
17. oktober 2010 - 20:15 #17
Ja.

Måske indtil:

modtaget bytes == total size
Avatar billede tetrix Nybegynder
17. oktober 2010 - 20:28 #18
Du får lige noget kode, for den er gal igen. Den ser ud til at gå over den 'aftalte' størrelse.

Modtager:
                        Dim frameSize As Integer = 0, sizeByte(4) As Byte
                        If (s.Read(sizeByte, 0, 4) = 0) Then
                            'forbindelse lukket
                            Return
                        End If
                        frameSize = BitConverter.ToInt32(sizeByte, 0)
                        Dim n As Integer = s.Read(b, 0, 1024), downloaded As Integer = 0
                        Do Until downloaded = frameSize
                            If (n = 0) Then Exit Do 'forbindelse lukket
                            mmStream.Write(b, 0, n)
                            downloaded += n
                            n = s.Read(b, 0, 1024)
                        Loop

Sender:                                                bins.Write(BitConverter.GetBytes(ms.Length), 0, 4)
                            bins.Flush()
                            Dim readByte(1024) As Byte, n As Integer = ms.Read(readByte, 0, 1024)
                            While (n > 0)
                                'write
                                bins.Write(readByte, 0, n)
                                bins.Flush()
                                'read next
                                n = ms.Read(readByte, 0, 1024)
                            End While

Det er den rigtige size der modtages.
Avatar billede arne_v Ekspert
18. oktober 2010 - 03:33 #19
Jeg kan ikke umiddelbart se problemet.

Kan du forklare hvad du sender og hvad du modtager?
Avatar billede tetrix Nybegynder
18. oktober 2010 - 12:33 #20
Ja. Jeg modtager størrelsen korrekt og sætter den. Modtager også data, men den stopper ikke, for jeg modtager langt over det aftalte.
Avatar billede arne_v Ekspert
18. oktober 2010 - 21:16 #21
Ah.

proev og erstat:

s.Read(b, 0, 1024)

med:

s.Read(b, 0, Math.Max(1024,frameSize-downloaded))
Avatar billede tetrix Nybegynder
18. oktober 2010 - 23:33 #22
Med den metode får jeg en OutOfArray exception, fordi Math.Max(1024,frameSize-downloaded) = frameSize.

Lavede lige endnu en test, og den bliver ved med at læse forevigt, selvom klienten faktisk stopper med at sende før modtageren overhovedet har modtaget den 'aftalte' størrelse. Det virker meget underligt.
Avatar billede arne_v Ekspert
18. oktober 2010 - 23:36 #23
Min fejl !

Math.Min ikke Math.Max
Avatar billede tetrix Nybegynder
19. oktober 2010 - 00:48 #24
Dim n As Integer = s.Read(b, 0, Math.Min(1024, frameSize - mmStream.Length))
                        Do Until mmStream.ToArray().Length = frameSize
                            If (n = 0) Then Exit Do 'forbindelse lukket
                            mmStream.Write(b, 0, n)
                            s.Read(b, 0, Math.Min(1024, frameSize - mmStream.Length))
                        Loop

Læser stadig videre.

Desuden stopper senderen ved omkring 40.000 bytes ved en frame der er 70.000 stor.
Avatar billede arne_v Ekspert
19. oktober 2010 - 02:09 #25
Du må prøve og udskrive n, mmStream.Length og frameSize for at finde ud af hvor det går galt.
Avatar billede tetrix Nybegynder
19. oktober 2010 - 14:19 #26
Gerne.

http://pastebin.com/VR8BqVrw

Som du kan se er n stadig 1024, selv når vi når over længden. Lige pt. sender klienten kun en gang, så den burde slet ikke komme så langt.
Avatar billede arne_v Ekspert
20. oktober 2010 - 04:03 #27
Det ser mystisk ud.

Hvordan ser Math.Min(1024, frameSize - mmStream.Length) ud i løkken ?
Avatar billede tetrix Nybegynder
20. oktober 2010 - 17:37 #28
Første frame sendes nu uden problematik.
Ved anden frame modtages en ugyldig størrelse, dvs. negativ eller forhøjet.

Sådan ser modtageren ud:

                        Dim b(1024 - 1) As Byte
                        Dim frameSize As Integer = 0, sizeByte(4 - 1) As Byte
                        If (s.Read(sizeByte, 0, sizeByte.Length) = 0) Then
                            'forbindelse lukket
                            Return
                        End If
                        frameSize = BitConverter.ToInt32(sizeByte, 0)
                        Dim n As Integer = s.Read(b, 0, Math.Min(b.Length, frameSize - mmStream.Length))
                        Do Until mmStream.Length >= frameSize
                            If (n = 0) Then
                                'forbindelse lukket
                                Return
                            End If
                            'skriv
                            mmStream.Write(b, 0, n)
                            'læs
                            n = s.Read(b, 0, Math.Min(b.Length, frameSize - mmStream.Length))
                        Loop
                        GoTo receiveFrameSize
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester