Announcement

Collapse
No announcement yet.

TCP/IP-Client mit Multithreading

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • TCP/IP-Client mit Multithreading

    Hallo zusammen,

    ich bin erst seit kurzem von VB6 auf VB.NET 2008 umgestiegen und
    komme mit dem nachfolgenden Problem einfach nicht weiter.

    Ich möchte mit meiner Anwendung mehrere TCP/IP Geräte steuern.
    Die Endgeräte arbeiten als Server, sind aber keine PCs.

    Nun muß die Anwendung also mehrere Instanzen eines TCPClients
    erzeugen können, welche ich dann einzeln behandeln kann.

    Der folgende Code ist in der Lage mit einem einzelnen Gerät zu
    kommunizieren, bei mehreren wird jedoch immer nur das letzte
    angesprochen. Bitte um Hilfe.

    [highlight=vbnet]Imports System.Net.Sockets
    Imports System.Net
    Imports System.IO
    Imports System.Threading
    Imports System.Text

    ' This stores data about each Device
    Public Structure deviceData
    Public tcpClient As TcpClient
    Public tcpStream As NetworkStream
    Public tcpIP As IPAddress
    Public tcpThread As Thread
    End Structure

    Public Class Form1

    Public readBuffer() As Byte
    Public writeBuffer() As Byte
    Private Shared connectId As Long = 0
    Private dataHolder As New Hashtable()
    Private tcpListen As TcpListener

    Private Function getDevices() As List(Of Devices)
    Dim devicelist As New List(Of Devices)()

    Dim device As New Devices
    device.Id = 1
    device.Ip = "192.168.115.35"
    devicelist.Add(device)
    device.Id = 2
    device.Ip = "192.168.115.36"
    devicelist.Add(device)

    Return devicelist
    End Function

    Public Sub connectDevices()

    Dim devicelist As List(Of Devices) = getDevices()

    For Each Devices In devicelist
    Dim devData As New deviceData
    Interlocked.Increment(connectId)
    devData.tcpClient = New TcpClient
    devData.tcpIP = IPAddress.Parse(Devices.Ip)
    devData.tcpClient.Connect(devData.tcpIP, 8000)
    devData.tcpStream = devData.tcpClient.GetStream()
    devData.tcpThread = New Thread(AddressOf ReadSocket)
    SyncLock Me
    ' it is used to keep connected Sockets and active thread
    dataHolder.Add(connectId, devData)
    upDateDataGrid(("Connected > " & connectId & " " & DateTime.Now.ToLongTimeString()))
    End SyncLock
    devData.tcpThread.Start()

    Next

    End Sub 'startServer



    Public Sub ReadSocket()

    Dim realId As Long = connectId
    Dim devData As deviceData = CType(dataHolder(realId), deviceData)
    Dim ret As Integer = 0
    While True
    Try
    readBuffer = New [Byte](100) {}
    devData.tcpStream.Read(readBuffer, 0, 100)
    Debug.Print(devData.tcpIP.ToString & ":" & System.Text.Encoding.ASCII.GetString(readBuffer) & ControlChars.Cr & ControlChars.Lf)
    Catch e As ThreadAbortException
    Catch e As Exception
    Exit While
    End Try
    End While

    End Sub 'ReadSocket

    Public Sub upDateDataGrid(ByVal displayString As String)
    Debug.Print((displayString & ControlChars.Cr & ControlChars.Lf))
    End Sub 'upDateDataGrid

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    tcpListen = New TcpListener(System.Net.IPAddress.Parse("127.0.0.1" ), 8000)
    tcpListen.Start()

    connectDevices()
    End Sub
    End Class[/highlight]
    Zuletzt editiert von gfoidl; 23.06.2009, 18:27. Reason: Code Formatierung auf VB.net umgestellt

  • #2
    Hallo,

    hab den Code kurz überflogen und dabei diesen Abschnitt als Bug geortet.
    [highlight=vbnet]
    Private Function getDevices() As List(Of Devices)
    Dim devicelist As New List(Of Devices)()

    Dim device As New Devices

    device.Id = 1
    device.Ip = "192.168.115.35"
    devicelist.Add(device)

    device.Id = 2
    device.Ip = "192.168.115.36"
    devicelist.Add(device)

    Return devicelist
    End Function
    [/highlight]
    Was passiert hier?
    1. Es wird eine Liste erstellt - korrekt
    2. es wird eine Instanz von Devices erstellt - korrekt
    3. es wird die ID und die IP-Adresse gesetzt - korrekt
    4. es wird dieses Device der Liste hinzugefügt - korrekt
    5. es wird die ID und die IP-Adresse von DIESEM Device geändert - falsch
    6. es wird das Device (das selbe) erneut der Liste hinzugefügt


    D.h. für das zweite Device muss eine neue Instanz erstellt werden.
    [highlight=vbnet]
    Private Function getDevices() As List(Of Devices)
    Dim devicelist As New List(Of Devices)()

    Dim device As New Devices

    device.Id = 1
    device.Ip = "192.168.115.35"
    devicelist.Add(device)

    ' neue Instanz erstellen:
    device = New Devices

    device.Id = 2
    device.Ip = "192.168.115.36"
    devicelist.Add(device)

    Return devicelist
    End Function
    [/highlight]

    mfG Gü
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      Schon mal vielen Dank für den Hinweis.
      Dadurch bleibt das Problem jedoch bestehen.

      Nur das letzte (in diesem Fall zweite) Device
      gibt Daten aus.

      Scheibar liegt das Problem daran, daß der erste Thread
      gar nicht gestartet wird, bevor die Schleife den nächsten
      Thread starten will, denn setze ich nach dem ThreadStart
      einen Breakpoint und warte auf die erste eingehende Meldung
      des ersten Devices, und lasse das Projekt dann weiterlaufen,
      dann kommen die Daten von beiden Devices rein.

      Allerdings klappt dies auch nur sehr kurz, bis das Direktfenster
      plötzlich im Millisekundenbereich zugespammt wird und die
      Anwendung hängt (Beendigung nur mittels Taskmanager)

      Bitte um weitere Hilfe.
      Zuletzt editiert von Resakier; 24.06.2009, 10:48.

      Comment


      • #4
        Was passiert wenn der Thread vor Synclock.Me gestartet wird?

        mfG Gü
        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

        Comment


        • #5
          Hallo,

          dann funktioniert es auf Anhieb, aber auch nur kurz.

          Nach einigen Meldungen kommen dann nur noch die Signale von
          dem ersten Leser.

          Comment


          • #6
            Hallo,

            irgendwie sieht das mit dem globalen readBuffer, der von allen Threads benutzt wird, komisch aus. Probier mal was in der Art:

            Code:
            Public Sub ReadSocket()         
            Dim realId As Long = connectId        
            Dim devData As deviceData = CType(dataHolder(realId), deviceData)        
            Dim ret As Integer = 0        
            Dim readBuffer        
            
            While True            
              Try                
                 readBuffer = New [Byte](100) {}                
                devData.tcpStream.Read(readBuffer, 0, 100)                
                Debug.Print(devData.tcpIP.ToString & ":" & System.Text.Encoding.ASCII.GetString(readBuffer) & ControlChars.Cr & ControlChars.Lf)            
               ' ReadBuffer wieder freigeben ?! 
               Catch e As ThreadAbortException            
               Catch e As Exception                
                  Exit While            
            End Try        
            End While     
            End Sub 'ReadSocket
            Ich habs gleich!
            ... sagte der Programmierer.

            Comment


            • #7
              Stimmt, das war das Problem.
              Vielen Dank für die Hilfe.

              MfG, Resakier

              Comment

              Working...
              X