Senden eine NetworkStreams

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von Thisoft.

    Senden eine NetworkStreams

    Hallo,

    ich habe mich schon recht erfolgreich durch das TCP-Tutorial durchgewühlt. Der Aufbau der Connection und das Senden/Empfangen von diversen Textzeilen klappt auch problemlos. Allerdings möchte ich jetzt einen Networkstream versenden und sehe gerade den Wald vor lauter Bäumen nicht mehr wie ich denn nun den Stream "auf die Reise schicken" muss... Hier mal mein Code

    VB.NET-Quellcode

    1. Private Sub SendToClient(ByVal s As NetworkStream, ByVal TargetID As String)
    2. For Each c As Connection In list ' an alle clients weitersenden.
    3. If c.ClientID = TargetID Then
    4. Try
    5. c.stream = s
    6. Ich glaube, hier fehlt was...
    7. 'c.streamw.WriteLine(s)
    8. 'c.streamw.Flush()
    9. Catch
    10. End Try
    11. End If
    12. Next
    13. End Sub


    Könnt Ihr mir mal 'nen kurzen Schlag auf den Hinterkopf geben?
    Oh - wenn das so ist habe ich da in den Tut's was falsch verstanden ?(
    Also, mal von weiter vorn angefangen:
    Ich möchte (oder besser: muss! weil es für diese ...Ingres-Db keinen 64-bit ODBC-Treiber gibt X( ) sozusagen einen Datenbankserver programmieren. Dazu habe ich mir gedacht, dass ich den jeweiligen SQL-Befehl als String vom Client an den Server schicke, die daraus resultierende DataTable in einen Stream packe und eben diesen Stream zurück an den Client sende. Bis zum Füllen des Streams klappt das ja auch schon. Nur wie's dann mit dem Versenden weiter geht hängt's bei mir gerade ein wenig...

    Vielen Dank für Eure Hilfe
    Tja, genau das will ich ja im Prinzip machen. Allerdings hänge ich da jetzt etwas durch ;(
    Ich hatte mir jetzt gedacht, dass ich mittels "DataTable.WriteXml" die Daten direkt in den Stream schreibe, aber wie muss ich dann vorgehen um die Daten auch wirklich zu senden?

    Andere Möglichkeit wäre vielleicht die Daten in ein ByteArray zu schieben und das dann zu senden...(ja?;nein?;vielleicht?)

    Sorry für die Fragerei, aber habe eben bisher noch nie was mit Netzwerkprogrammierung getan... Wäre schön, wenn mich hier mal jemand übers Prinzip aufklären könnte.

    Danke und Gruß
    du kannst doch direkt in den NetworkStream schreiben lassen, das funktioniert gleich wie bei jedem anderen Stream auch...
    Andernfalls(wie du selbst schon gesagt hast) als ByteArray versenden, dafür gibt es (geerbt von System.IO.Stream) die Write Methode...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ja, das Schreiben in den Stream ist mir ja soweit auch klar, aber dann...??
    So gibt es zwar keine Fehler, aber es kommt auch beim Client nichts an!

    VB.NET-Quellcode

    1. Private Sub SendToClient(ByVal s As DataTable, ByVal TargetID As String)
    2. For Each c As Connection In list ' an alle clients weitersenden.
    3. If c.ClientID = TargetID Then
    4. Try
    5. s.WriteXml(c.stream)
    6. 'Ich weiß nicht was hier stehen muss??????!!!!!
    7. Catch
    8. End Try
    9. End If
    10. Next
    11. End Sub
    In der Tat - das Problem lag wohl nicht mehr am Senden, sondern beim Empfangen.

    Ich habe im Client jetzt folgenden Code:

    VB.NET-Quellcode

    1. Private Sub Listen()
    2. While client.Connected
    3. Try
    4. 'Me.Invoke(New DAddItem(AddressOf AddItem), streamr.ReadLine)
    5. Me.Invoke(New DReceiveData(AddressOf ReceiveData), stream)
    6. Catch
    7. MessageBox.Show("Verbindung zum Server nicht möglich!")
    8. Application.Exit()
    9. End Try
    10. End While
    11. End Sub
    12. Private Sub AddItem(ByVal s As String)
    13. ListBox1.Items.Add(s)
    14. End Sub
    15. Private Sub ReceiveData(ByVal DatStream As NetworkStream)
    16. Dim RecDat As New DataTable
    17. RecDat.ReadXml(DatStream)
    18. MessageBox.Show(RecDat.Rows.Count)
    19. End Sub


    Dabei habe ich jetzt diese Geschichte mit Invoke... nach bestem Wissen und Gewissen gegenüber dem Empfangen von Strings abgewandelt. Aber das funktioniert so nicht. Der Client beendet die Verbindung sobald Daten ankommen bzw. hängt sich sogar auf.

    Könnt Ihr mir bitte noch einen Tip geben, wie ich den Stream jetzt empfangen muss?
    mach auch hier am besten das Try weg, ich vermute, dass die DataTable bei ReadXml Seek verwendet(evtl. um die größe herauszubekommen o.ä. das funktioniert bei einem NetworkStream nicht...)

    Mach am besten eine eigene Routine, welche zuerst die kompletten XML Daten einliest(z.B. als String) und erst dann verarbeitet...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Kan man eine klasse durch dass Netzwerck hindurch eigendlich Serialisieren und dann wieder deserialisieren, ich habe es mit den BinaryForrmatter versucht, aber irgendwas scheint gerade nicht zu klappen!
    Hilfeeeee - ich bin jetzt annähernd komplett verwirrt ?(

    ich komme mit dem Empfangen nicht weiter. Wenn ich einen String zurück an den Client sende und dem entsprechend die Zeile

    VB.NET-Quellcode

    1. Me.Invoke(New DAddItem(AddressOf AddItem), streamr.ReadLine)


    verwende, klappt alles. Wenn ich's dann aber mit dem Stream versuche und die andere Invoke-Zeile

    VB.NET-Quellcode

    1. Me.Invoke(New DReceiveData(AddressOf ReceiveData), stream)


    beendet der Client die Verbindung sobald Daten gesendet werden - allerdings ohne Fehlermeldung(Try habe ich weggelassen)

    Kann mir das bitte mal jemand erklären, wie ich da vorgehen muss?
    Serialisierung klingt auch, als ob ich das evtl. nutzen könnte, aber das habe ich nun auch noch nie verwendet...

    Eigentlich kann es ja nicht so schwer sein - ich muss es nur erstmal verstehen :rolleyes:
    Ich habe eine Serialisierbare klasse gemacht, dass Attribut am anfang der Klasse! Aber wie bekomme ich diese durch,s netzwerck zu meinen Server um sie dort wieder zu deserialisieren?? Und vor allendingen wie Serialisiere ich es alles durch,s netzwerck! In eine Datei ist mir schon klar, aber durchs netzwerck??
    Hallo zn-gong,

    ich weiß nicht ob Dein Problem noch besteht und ob Dir meine Lösung hilft, aber ich hab's jetzt hinbekommen. Ich poste hier mal meine Lösung - vielleicht kann es ja jemand gebrauchen:

    Zuerst der Server:

    Das Interessante daran dürfte die Funktion "GetDataAsString" sein...

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal con As Connection)
    2. Do
    3. Try
    4. Dim tmp As String = con.streamr.ReadLine ' warten, bis etwas empfangen wird...
    5. Console.WriteLine("von " & con.ClientID & ": " & tmp)
    6. If tmp Like "SELECT*" Then
    7. Dim DatStr As String = GetDataAsString("betrieb03", tmp)
    8. SendToClient(DatStr, con.ClientID)
    9. Else
    10. SendToClient("SQL-Statement noch nicht implementiert!", con.ClientID)
    11. End If
    12. Catch ex As Exception ' die aktuelle überwachte verbindung hat sich wohl verabschiedet.
    13. list.Remove(con)
    14. Console.WriteLine(ex.Message)
    15. Console.WriteLine(con.ClientID & " has exit.")
    16. Exit Do
    17. End Try
    18. Loop
    19. End Sub
    20. Private Sub SendToClient(ByVal s As String, ByVal TargetID As String)
    21. For Each c As Connection In list ' an alle clients weitersenden.
    22. If c.ClientID = TargetID Then
    23. If Test Then
    24. c.streamw.WriteLine("Teststring")
    25. c.streamw.Flush()
    26. Else
    27. c.streamw.WriteLine(s)
    28. c.streamw.Flush()
    29. End If
    30. End If
    31. Next
    32. End Sub
    33. Private Function ConnectToERP(ByVal Datenbank$, ByVal SQLString$) As DataTable
    34. Dim conn03 As Odbc.OdbcConnection, Commando As New Odbc.OdbcCommand, connString As String, TAdaptArtikel03 As New Odbc.OdbcDataAdapter, DataArtikel03 As New DataTable
    35. Dim dsCount%
    36. connString = "DRIVER=Ingres; SRVR=KPSSERV2_I3; Database=" & Datenbank
    37. conn03 = New Odbc.OdbcConnection(connString)
    38. Commando.Connection = conn03
    39. Commando.CommandText = SQLString
    40. Try
    41. conn03.Open()
    42. TAdaptArtikel03.SelectCommand = Commando
    43. dsCount = TAdaptArtikel03.Fill(DataArtikel03)
    44. Console.WriteLine(SQLString & " hat " & dsCount & " Datensätze zurückgegeben!")
    45. Catch ex As Exception
    46. Console.WriteLine(ex.Message)
    47. End Try
    48. Return DataArtikel03
    49. End Function
    50. Private Function GetDataAsString(ByVal Datenbank$, ByVal SQLString$) As String
    51. Try
    52. Dim daten As DataTable = ConnectToERP(Datenbank, SQLString)
    53. Dim StreamIn As New IO.MemoryStream
    54. daten.TableName = "SendTable"
    55. daten.WriteXml(StreamIn)
    56. Dim BytAry() As Byte = StreamIn.ToArray
    57. Dim SendString As String = Convert.ToBase64String(BytAry)
    58. Console.WriteLine(Len(SendString))
    59. Return SendString
    60. Catch ex As Exception
    61. Console.WriteLine(ex.Message)
    62. Return ""
    63. End Try
    64. End Function
    65. End Module



    Und hier noch der Client:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Listen()
    2. Dim ReDaten As New DataTable
    3. While client.Connected
    4. Me.Invoke(New DAddItem(AddressOf AddItem), streamr.ReadLine)
    5. End While
    6. End Sub
    7. Private Sub AddItem(ByVal s As String)
    8. 'ListBox1.Items.Add(s)
    9. Dim newms As New IO.MemoryStream
    10. Dim b() As Byte = Convert.FromBase64String(s)
    11. newms.Write(b, 0, b.Length)
    12. Dim DAten As New DataSet
    13. newms.Position = 0
    14. DAten.ReadXml(newms)
    15. MessageBox.Show(DAten.Tables(0).Rows.Count)
    16. End Sub



    Da das nur zum Testen per Try-and-Error diente habe ich noch nichts in Klassen verpackt usw. usw.

    Gruß Thilo