Socket Bytes in Outbuffer

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von demmy.

    Socket Bytes in Outbuffer

    Hi zusammen,

    ich hätte mal eine Frage, wenn ich Daten über eine TCP/IP-Verbindung schicke, mal angenommen einen String mit 10 Zeichen, gibt es eine möglichkeit zu ermitteln,
    wieviele Bytes gerade im ausgangsbuffer sind.
    Oder generell ob die Schnittstelle gerade am Senden ist?

    Viele Grüße
    Hey,

    ich glaube nicht, dass es im FrameWork hier Möglichkeiten gibt, dies in Erfahrung zu bringen. Beim Senden bekommst Du die Anzahl der an den Socket übergebenen Bytes zurück. Sieht man sich die Socket-Klasse in IL-Spy an, so sieht man auch nur noch den API-Aufruf und dann "verliert sich die Spur". Für Dich ist wichtig zu wissen, ob alle Bytes übergeben wurden, den Rest kannst Du nicht beeinflussen. Jedenfalls ist mir nichts bekannt.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Hi
    wenn ich es richtig interpretiere, möchtest du schauen, ob ein String fertig übertragen wurde, oder? Übertrage in diesem Fall einfach einige Metadaten dazu:
    Die Daten bestehen hierbei immer aus einem Header und den nachfolgenden Daten selbst. Der Header stellt bspw. die Länge des nachfolgenden Datenblocks in Bytes bereit. Die Bytes werden solange ausgelesen, bis ein Puffer mit der Länge des Datenblocks vollständig befüllt wurde. Anschließend werden diese Daten in einen String umgewandelt. Zur Umwandlung kannst du eben System.Text.Encoding.Unicode.GetString und .GetBytes verwenden, um die Bytes einzulesen genügt eine While-Schleife (ggf. mit einer Zeit-Verzögerung), ein Byte-Array (der Zielpuffer) und eine Zählvariable:
    Lesen:

    VB.NET-Quellcode

    1. Dim count As Integer
    2. Dim buffer(3) As Byte
    3. ReadBytes(buffer, 0, 4)
    4. count = BitConverter.ToInt32(buffer, 0)
    5. buffer = New Byte(count -1) { }
    6. ReadBytes(buffer, 0, count)
    7. MessageBox.Show(System.Text.Encoding.Unicode.GetString(buffer))

    Schreiben:

    VB.NET-Quellcode

    1. Dim bytes() As Byte = System.Text.Encoding.Unicode.GetBytes(text)
    2. _underlyingStream.Write(BitConverter.GetBytes(bytes.Length)), 0, 4)
    3. _underlyingStream.Write(bytes, 0, bytes.Length)

    benötigt

    VB.NET-Quellcode

    1. Private Sub ReadBytes(buffer() As Byte, index As Integer, count As Integer)
    2. While count > 0
    3. Dim len As Integer = _underlyingStream.Read(buffer, index, count)
    4. index += len
    5. count -= len
    6. End While
    7. End Sub


    Gruß
    ~blaze~
    Hi Jungs,
    danke schon mal für euere Ideen.

    Worum es mir dabei aber eigentlich geht ist zu überprüfen ob der "Kanal" frei ist für das nächste Datenpaket.
    Wenn z.b. verschiedene Threats Daten über den selben Socket senden wollen.

    ich hoffe, ihr versteht wie ich das meine?

    Gruß
    Hallo zusammen,
    ich bin leider nun immer noch nicht wirklich weiter gekommen.

    Ich habe es nun zuletzt mal auf folgendem Weg versucht.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Befehlsliste As New List(Of Object)
    2. Public Befehle_absetzen_aktiv As Boolean
    3. #Region "methods to send data by different threads"
    4. Public Sub Befehl_Senden(ByVal msgTag As Byte)
    5. ' Eintrag zur Befehlsliste hinzufügen
    6. Dim Eintrag() As Object = {(1), (msgTag)}
    7. Befehlsliste.Add(Eintrag)
    8. If Befehle_absetzen_aktiv = False Then
    9. Befehle_absetzen_aktiv = True
    10. Dim th As New Thread(AddressOf Befehle_absetzen)
    11. th.Start()
    12. End If
    13. End Sub
    14. Public Sub Befehl_Senden(ByVal msgTag As Byte, ByVal strX As String)
    15. ' Eintrag zur Befehlsliste hinzufügen
    16. Dim Eintrag() As Object = {(2), (msgTag), (strX)}
    17. Befehlsliste.Add(Eintrag)
    18. If Befehle_absetzen_aktiv = False Then
    19. Befehle_absetzen_aktiv = True
    20. Dim th As New Thread(AddressOf Befehle_absetzen)
    21. th.Start()
    22. End If
    23. End Sub
    24. Private Sub Befehle_absetzen()
    25. Do While Befehlsliste.Count > 0
    26. Do Until Daten_werden_gesendet = False
    27. System.Threading.Thread.Sleep(10)
    28. Loop
    29. Dim Eintrag() As Object = CType(Befehlsliste.Item(0), Object())
    30. ' Anhand des Eintrages wird die eigentliche Sendefunktion aufgerufen
    31. Select Case CType(Eintrag(0), Integer)
    32. Case 1 : Send(CType(Eintrag(1), Byte))
    33. Case 2 : Send(CType(Eintrag(1), Byte), CType(Eintrag(2), String))
    34. End Select
    35. ' Aktuell abgesetzten Befehl löschen
    36. Befehlsliste.RemoveAt(0)
    37. Loop
    38. Befehle_absetzen_aktiv = False
    39. End Sub
    40. #End Region


    füge ich in einer Schleife aus verschiedenen Threads auf einmal 100 Befehle zur Liste hinzu, hängt sich das Programm auf einmal auf, hat jemand evtl. eine Idee wieso?

    Viele Grüße
    ja, das hab ich soweit schon verstanden,

    deshalb habe ich ja versucht, das in den verschiedenen threads nur eine List(of Object) gefüllt wird.
    Und in einem "Sende"-Thread wird dann ein Befehl nacheinander aus der Liste geholt und gesendet.
    Aber scheinbar läuft beim füllen der Liste schon irgendwas schief!? kann das sein?

    Die Sendefunktionen selbst sind mit einem Synclock versehen.

    Gruß

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

    Du scheinst grundsätzliche Probleme bei Parallelisierung und Synchronisation zu haben.
    Ich vermute der bessere Ansatz wäre genau zu beschreiben, welches Ziel du hast.
    Das ist meine Signatur und sie wird wunderbar sein!
    Hi,

    also das Ziel soll folgendes sein:

    Ich möchte aus verschiedenen Threads heraus, eine Liste mit Befehlen füllen. Diese Liste soll dann nacheinander mittels Tcp/Ip übertragen werden.
    Sobald ein Befehl in der Liste eingegangen ist, soll ein Thred gestartet werden der die Liste abarbeitet (die einzelnen Befehle sendet).
    Während das passiert, kann es aber vorkommen, das neue Befehle zur Liste hinzugefügt werden, welche dann auch übertragen werden sollen.

    ich hoffe ich konnte euch das verständlich rüber bringen?


    und ich bin mit der fehlersuche einen großen Schritt weiter gekommen.

    ich verwende jetzt dank eueres hinweises: ConcurrentQueue(Of Object)

    weiter habe ich festgestellt, das das Problem an dieser stelle hier liegt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Do Until Daten_werden_gesendet = False
    2. System.Threading.Thread.Sleep(10)
    3. Loop


    ich warte wohl nicht lange genug mit dem Senden des nachfolgenden Befehls bis der vorherige vollständig rausgegangen ist, d.h. das Bit Daten_werden_gesendet wird wohl nie True. Deshalb kommt es wohl zu Überschneidungen und mein Programm hängt sich auf.

    Nun, Das Bit setze ich so:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Send(ByVal msgTag As Byte)
    2. Daten_werden_gesendet = True
    3. Try
    4. SyncLock client.GetStream
    5. Dim writer As New BinaryWriter(client.GetStream)
    6. writer.Write(RequestTags.ByteTransfer)
    7. writer.Write(msgTag)
    8. writer.Flush()
    9. End SyncLock
    10. Catch ex As Exception
    11. End Try
    12. Daten_werden_gesendet = False
    13. End Sub


    ich glaube aber, das ist so nicht korrekt oder?

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

    Nimm halt VS2012, TPL Dataflow und nen ActionBlock

    VB.NET-Quellcode

    1. Imports System.Threading.Tasks.Dataflow
    2. Public Class Form1
    3. Private DerSender As New Dataflow.ActionBlock(Of String)(AddressOf SenderSub)
    4. Private Sub SenderSub(ByVal s As String)
    5. Console.WriteLine("Got and processed: {0}", s)
    6. End Sub
    7. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    8. Parallel.For(1, 100, Sub(i As Integer)
    9. Dim r As New Random(12345678 + i)
    10. Threading.Thread.Sleep(r.Next(50, 500))
    11. DerSender.Post("Thread " & Threading.Thread.CurrentThread.ManagedThreadId.ToString & " = " & i.ToString)
    12. End Sub)
    13. End Sub
    14. End Class