Hilfe bei TCP daten senden und empfangen

  • VB.NET

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

    Hilfe bei TCP daten senden und empfangen

    Hallo, ich möchte über TCP daten an ein externes Gerät senden und empfangen. Und zwar in sollen die Daten folgende Form haben: Header(8 Byte Folge), Data(1-10Byte Folge) Trailer(CRC Algorythmus). An jeder Byte Pos steht eine Bit folge oder ein Word z.B.: 0x0001
    Ich habe den hier im Forum vorgeschlagenden Code ausprobiert und das connecten klappt. Wie muss ich die Teil zum senden und empfangen umschreiben dass ich die entsprechenden Daten empfangen/senden kann. Hier mein bisheriger code:

    VB.NET-Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Public Class Form1
    4. Dim stream As NetworkStream
    5. Dim streamw As StreamWriter
    6. Dim streamr As StreamReader
    7. Dim client As New System.Net.Sockets.TcpClient
    8. Dim IP As String
    9. Dim Port As Integer = 8000
    10. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    11. IP = TextBox1.Text
    12. Try
    13. Client.Connect(IP, Port)
    14. If Client.Connected Then
    15. MsgBox("Verbidnung konnte mit " & IP & " Aufgebaut werden!")
    16. stream = Client.GetStream ' Stream wird auf Client verwiesen
    17. streamw = New StreamWriter(stream) ' Stream zum Senden wird deklariert
    18. streamr = New StreamReader(stream) ' Stream zum Empfangen wird deklariert
    19. Else
    20. MsgBox("Verbidnung konnte nicht mit " & IP & " aufgebaut werden!")
    21. End If
    22. Catch ex As SocketException
    23. MsgBox("Verbidnung konnte nicht mit " & IP & " aufgebaut werden!")
    24. End Try
    25. End Sub
    26. Sub client_send(ByVal text As String)
    27. streamw.WriteLine(text)
    28. streamw.Flush()
    29. End Sub
    30. Function client_recieve() As String
    31. client_recieve = streamr.ReadLine
    32. End Function
    33. End Class


    Außerdem habe ich noch eine Frage: Ich habe in verschieden Tutorial zum senden von Text/daten über TCP die verwendung eines tcplistener gesehen. Welche Vorteile bringt der?

    Vielen Dank
    Verwende BinaryWriter und BinaryReader anstatt StreamWriter und StreamReader.
    Dann kannst du die Daten binär senden und empfangen.
    TCPListener stellt den Server dar...

    Zum senden würde ich dir eher den BinaryWriter/Reader empfehlen, einfach StreamWriter/Reader ersetzen, anschließend kannst du mit Write bzw. Read einzelne Bytes schreiben/lesen, oder mit ReadInt32 sogar ganze Integer versenden(und natürlich auch empfangen)...

    Steht immerhin noch TCPListener drinne :P
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Vielen Dank

    Vielen Dank erstmal. Hab den BinaryReader/Writer eingebaut. Jetzt hab ich das Problem wie die Werte z.B aus dem Header oder Data einbaue.
    Für einen Test sollen folgedne Werte übermittelt werde:

    Header
    Byte pos _Data _____type Description
    0________WORD ____Transmitter ID
    2 _______BYTE _____0x03
    3 _______BYTE_____ 0x01
    4 _______WORD ____0x0000
    6 _______WORD____ Continuously incremented,
    __________________starting with 0x0000 after the connection has been established
    8 _______WORD____ 0x0002

    Data
    10 ______Byte_____ Bit0: 0:...
    _______________________1:...

    Hatte überlegt die werte einfach in ein Array zu schreiben aber ich denke da mache ich es mir zu einfach:

    VB.NET-Quellcode

    1. Sub client_send(ByVal text As String)
    2. Dim Zum_Senden(7) As String
    3. Zum_Senden = {"192.168.1.12", "0", "0x03", "0X01", "0", "0x0000", "0", "0x0002"}
    4. For i As Integer = 0 To 7
    5. streamw.Write(Zum_Senden(i))
    6. streamw.Flush()
    7. Next

    Hab ihr eine Idee wie ich das umsetzten könnte?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Karo“ ()

    en.wikipedia.org/wiki/Integer_%28computer_science%29
    Wie du siehst entspricht Word einem Zahlenwert, 2 Byte groß-> Short bzw. UShort(Int16/UInt16)
    Hex Zahlen werden in VB mit &H dargestellt...

    VB.NET-Quellcode

    1. streamw.Write(CUShort(TransmitterID))
    2. streamw.Write(CByte(&H3))
    3. streamw.Write(CByte(&H1))
    4. streamw.Write(CUShort(0))
    5. streamw.Write(CUShort(inkrementedNumber))
    6. streamw.Write(CUShort(&H2))

    so könnte der Header aussehen(sofern die Bytes und Words, welchen eine Hex-Zahl folgt, wirklich feste Werte sind)...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    du musst streamw auch setzen...
    streamw = New StreamWriter(stream) ' Stream zum Senden wird deklariert
    streamr = New StreamReader(stream) ' Stream zum Empfangen wird deklariert

    Das was du mit dem StreamWriter/reader gemacht hast, musst du auch mit dem BinaryReader/Writer machen
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Danke erstmal, das Senden klappt jetzt:
    So ich habe nun die letzten Tage versucht mit dem externen Gerät zu kommunizieren.
    Lese ich die übermittelten Daten als 1 oder 2 Bytefolgen so wie es nach dem Communication Protocol gefordert ist bekomme ich an einigen Stellen negative Zahlen, obwohl es sich bei den übermittelnetn Daten um binäre folgen oder hex Zahlen handeln soll, worann kann das liegen?
    Lese ich die Daten als Byte-Array aus kommen ganz andere aber sinnvollere Werte raus...? Zb. erste Byte Position (2 Byte lang) als ganzes gelesen -23293 als Array 3, 165 erwartet hatte ich 0xA503 oder 42243. Ich vermute dass die binäre Folge falsch in dezimal zahlen übersetzt wird.
    Außerdem scheint ein Probelm beim sende aufzutreten: Es soll zum beispiel die Hex-Zahl 02 übermittelt werden jedoch scheint der Compieler diese immer in 2 zu ändern. Anhand der zurück kommenden Daten ( nicht 2 nicht als 10 sondern 00000010 ). Wie kann ich vollständige 8 Bit ketten senden? Also nicht 10 für 2 sondern 00000010
    Der Quellcode für senden:

    VB.NET-Quellcode

    1. Dim B(2) As Byte
    2. stream = client.GetStream ' Stream wird auf Client verwiese
    3. streamw = New BinaryWriter(stream) ' Stream zum Senden wird deklariert
    4. streamw.Write(CUShort(&HA501))
    5. B(0) = Hex(2)
    6. streamw.Write(B(0))
    7. B(0) = Hex(1)
    8. streamw.Write(B(0))
    9. B(0) = Hex(0)
    10. B(1) = Hex(0)
    11. streamw.Write(B(0))
    12. streamw.Write(B(1))
    13. streamw.Write(CUShort(&H804))
    14. B(0) = Hex(2)
    15. B(1) = Hex(0)
    16. streamw.Write(B(0))
    17. streamw.Write(B(1))
    18. B(0) = Hex(0)
    19. B(1) = Hex(0)
    20. streamw.Write(B(0))
    21. streamw.Write(B(1))
    22. streamw.Write(CUShort(&HFFFF))
    23. streamw.Flush()


    Und der fürs emfangen:

    VB.NET-Quellcode

    1. Dim Stelle(5) As Byte
    2. Dim Andwort(6, 12) As Byte
    3. If stream.DataAvailable Then
    4. Stelle = streamr.ReadBytes(2) 'Byte Pos 0
    5. Andwort(0, 0) = Stelle(0)
    6. Andwort(1, 0) = Stelle(1)
    7. Stelle = streamr.ReadBytes(1) 'Byte Pos 2
    8. Andwort(0, 1) = Stelle(0)
    9. Stelle = streamr.ReadBytes(1) 'Byte Pos 3
    10. Andwort(0, 2) = Stelle(0)
    11. Stelle = streamr.ReadBytes(2) 'Byte Pos 4
    12. Andwort(0, 3) = Stelle(0)
    13. Andwort(1, 3) = Stelle(1)
    14. Stelle = streamr.ReadBytes(2) 'Byte Pos 6
    15. Andwort(0, 4) = Stelle(0)
    16. Andwort(1, 4) = Stelle(1)
    17. Stelle = streamr.ReadBytes(2) 'Byte Bos 8
    18. Andwort(0, 5) = Stelle(0)
    19. Andwort(1, 5) = Stelle(1)
    20. Stelle = streamr.ReadBytes(2) 'Byte Pos 10
    21. Andwort(0, 6) = Stelle(0)
    22. Andwort(1, 6) = Stelle(1)
    23. Stelle = streamr.ReadBytes(1)
    24. Andwort(0, 7) = Stelle(0) 'Byte Pos 12
    25. If stream.ReadByte = -1 Then
    26. Timer1.Stop()
    27. RichTextBox1.AppendText("Ende")
    28. client.Close()
    29. End If


    Das ausgelesene Array sieht dann so aus:
    0,0: 3 0,1: 165
    1,0: 255 1,1: 0
    2,0: 1 2,1: 0
    3,0: 0 3,1: 0
    4,0: 3 4,1: 8
    5,0: 2 5,1: 0
    6,0: 1 6,1: 0
    7,0: 206 7,1:0
    Ende


    Die 225 dedeutet Communication Error

    Aus der Stelle 5,0, 5,1 müsste zum Beispiel die hex Zahl 0x0020 ergeben..

    Vielen Dank
    Karo
    msdn.microsoft.com/en-us/library/963zt96e%28v=vs.80%29.aspx
    Ist eine veraltete VB 6 Funktion und solltest du nicht verwenden...
    zweitens ist der zurückgebene Type ein String also Text und du wandelst ihn direkt danach wieder in eine Zahl um, einen Text?! Das funktioniert nicht.
    Schreib am besten mal in die alleroberste Zeile deines Codes "Option Strict On"...
    dann wirst du viele Fehler bekommen, die du ausmerzen musst...
    Du könntest deine Hexzahlen in das Dualzahlensystem umrechenen, oder:
    Hex Zahlen werden in VB mit &H dargestellt...

    d.h. 0x01 -> &H01 bzw. 0xFF -> &HFF


    Wo/Wie liest du den als ganzes aus?
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Hallo, habe das Option Strict On mal ausprobiert es hat aber nur einen Fehler in der senden Funktion gefunden ich habe daraufhin wieder meine alte Funktion verwendet. Ich vermute dass beim Senden, das Problem liegt: Die erste Zeile scheint noch Verstanden zu werden. Da nur eine Antwort gesendet wird, wenn die erste Zeile (Transmitter ID) richtig ankommt. Aber schon in der nächten Zeile scheint etwas nicht zu stimmen: Dort steht ein Code für die Art der Anfrage( z.B. 0x02 für Status der Lampen) abhänig von der Art der Anfrage sendet das Gerät unterschiedlich lange Datenpackete zurück. Leider ist der zurück kommende Stream immer gleich lang egal welche Anfrage ich stelle. Hier meine andere Sendefunktion:

    VB.NET-Quellcode

    1. streamw.Write(CUShort(&HA501))
    2. streamw.Write(CByte(&H2))
    3. streamw.Write(CByte(&H1))
    4. streamw.Write(CUShort(&H0))
    5. streamw.Write(CUShort(&H0))
    6. streamw.Write(CUShort(&H2))
    7. streamw.Write(CUShort(&H0))
    8. streamw.Write(CUShort(&HFFFF))
    9. streamw.Flush()


    jvbsl schrieb:

    zweitens ist der zurückgebene Type ein String also Text und du wandelst ihn direkt danach wieder in eine Zahl um, einen Text?!
    Da ich die ankommden Daten Byte weise auslesen muss verwende ich (wie empfohlen) áuch zum Lesen den BinaryReader. Dieser unterstüzt zwar ein auslesen als String, jedoch biete die Methode BinaryReader.ReadString nicht die möglichkeit auszuwählen wie viele Bytes gelesen werden sollen. Da ich aber immer Packete von 1-6 Bytes lesen muss hilft mir diese Methode nicht.Wie kann die die zurückgegeben Daten als String sonst lesen?

    jvbsl schrieb:

    Wo/Wie liest du den als ganzes aus?
    Ausgelesen wird das "Antwort-Array" über eine for schleife in eine RichTextBox:

    VB.NET-Quellcode

    1. For i As Int16 = 0 To 12 Step 1
    2. For j As Int16 = 0 To 5 Step 1
    3. RichTextBox1.AppendText(i & "," & j & ": " & Andwort(j, i) & " ")
    4. Next
    5. RichTextBox1.AppendText(vbCrLf)
    6. Next


    Falls es hilft die ankommenden Daten sollen genauso aufgebaut sein wie die zu sendenden:
    Byte Pos Typ Discription
    0 Word ID
    2 Byte 0x12
    und so weiter bis z.B Byte Pos 42
    Ich hoffe Option Strict On ist noch drinne ;)

    ReadString macht follgendes:
    liest als erstes vier Bytes und wandelt diese in eine INt32 Zahl um, anschließend verwendet er die Zahl als länge der zu empfangenden Zeichen...

    Außerdem denke ich nicht, dass die Daten als String ankommen...

    vielleicht würde es mir und dir helfen, wenn du mir mal nen Link zu dem Gerät und den entsprechenden Befehlen schickst. Es könnte ja sein, dass das Gerät BigEndian verwendet, .Net verwendet jedoch LittleEndian, dann müsste man das immernoch konvertieren...

    Außerdem wäre mir dann vlt. klar, welche Daten du auf welche Art darstellen/lesen möchtest...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---