VB.NET Multi Socket Server - Threads oder doch anders?

String

Erfahrenes Mitglied
Hallo zusammen,

ich bin gerade dabei einen Multi Socket Server mit VB.NET und Threads zu erstellen allerdings stehe ich dort vor einigen oder gar vielen Problemen.

Als Info: Der Server soll nachher als Mutli-Game Server dienen. Mit einigen (1 - 20 vllt) Spielern pro Server - wenn mehr möglich natürlich auch gerne mehr ;) ) Die Clienten werden alles Flash-Anwendungen sein.

So nehme ich derzeit eine Verbindung an:
Code:
client = Server.AcceptTcpClient()
Dim myThread As New Thread(AddressOf clientThreads)
myThread.Start()

Habe ich das soweit schonmal richtig verstanden oder bin ich ab da schon auf dem falschen Dampfer?
In dem "Sub" clientThreads, welches ja quasi kopiert und immer wieder ausgeführt wird, wird der Stream gelesen, oder?

Doch nun stehe ich vor einigen Fragen:
Wie lese ich dem Stream aus? Ich könnte ihn an der Thread übergeben
Code:
myThread.Start(stream)
und den Sub ala
Code:
private sub clientThreads(byval stream as networkstream)
aufrufen.

Aber dann habe ich das Problem das ich nicht die Nachricht die in Thread A empfangen wird an Thread B - Z zu senden. Desweiteren müssen die Clienten ja irgendwo "gespeichert" werden. Vielleicht in einem Array? Aber gibt es dort nicht eine schönere Möglichkeit?

Also irgendwie verstehe ich dieses "MULTI-SERVER" ding noch nicht so ganz. Kann mir dort mal jemand eine gescheite Übersicht Posten, wie das Ablaufen muss? Codes brauche ich eig. nicht, dass bekomm ich noch selber her, aber den Ablauf, verstehe ich nicht so ganz.

Eine einfache Server - Client verbindung bekomme ich Problemlos hin. Sobald aber mehrere Clienten auf einen Server zugreifen sollen und untereinander kommunizieren sollen hat sich das bei mir erledigt.

In meinen hunderten Versuchen hatte ich bisher eine "Struktur" die gelaufen ist, allerdings nicht das Gelbe vom Ei ist ;)
- Server Starten
- Client verbindung startet Thread und übergibt Client-Stream
- Bei Client-Verbindung wird in ein Array der Stream vom Clienten gespeichert.

- Thread:
-- Mit Loop stream auslesen
-- Empfangenen Text in ne Listbox (lol)

- Timer:
-- Listbox (mit empfangenen Text) durchlaufen und an andere Clienten weiterleiten die im Array gespeichert sind (...)


Das gab allerdings mehrere Probleme z.b. wenn der Client einfach geschlossen wurde aber nicht das "exit" kommando gesendet hat. Dann wurde er z.b. nicht aus dem Array gelöscht und es wurde die ganze zeit versucht weiter zu senden..

Also, ich bin für jeden tip SEHR dankbar.
Zum Thema Google: Ich habe schon viele hunderte Seiten gefunden. Habe auch schon schöne Code-Beispiele gefunden. Allerdings waren die meist ohne Erklärung oder absolut unverständlich.

Gruß
string
 

Alexander Schuc

crazy-weasel
Hi.

Erstelle eigene Klasse, welche für die direkte Kommunikation mit den Clients verantwortlich sind.

Wenn ein neuer Client verbindet (nach AcceptTcpClient) erstellst du eine Instanz der Klasse, übergibst dieser den TcpClient, und beim Erstellen des Threads gibst eine Methode dieses Objekts an.

Dann speicherst dieses Objekt in einer Liste, und bist ansich fertig mit diesem einen Client, und kannst auf den nächsten Thread warten.

Wenn du jetzt Nachrichten verschicken willst, brauchst nur deine Liste durchgehen, und mit jedem Objekt die Nachricht verschicken. Dabei kannst du diese "ClientKlasse" so gestalten, dass du auch gar nicht den direkten Zugriff auf den Stream brauchst, sondern über eine eigene Write Methode.

Zu deinem Problem, wenn ein Client die Verbindung beendet ohne den exit Befehl zu senden: Beim Schrieben kannst dann ja den Status des Streams abfragen, und wenn der Stream abbricht, wird (irgendwann) eine Exception geworfen, spätestens wenn du was schicken willst, und der Stream aber schon weg ist.

Hoffe das hilft dir mal weiter. ;)

lg,..
 

String

Erfahrenes Mitglied
Gut, soweit habe ich das ja eigentlich. Nur jetzt wieder meine Frage: Was für eine Liste? Ein Array? ListBox? DataTable? Hashtable? Welche ist am schnellsten? Welche eignet sich für meine zwecke?

Nehmen wir an:
Client A öffnet seinen Clienten und Connectet am Server. Der Server erstellt nun einen Thread (evt. mit einer Klasse) und hält dessen Stream offen. Dann öffnet sich ein weiterer Client B und Connectet am Server.

Jetzt habe ich auf dem Server eine Liste - wo Client A und B eingetragen sind. Bis auf dass ich nicht weiß welche Liste am besten ist, ist mir das soweit schonmal klar.

Jetzt: Wie sende ich vom Client A die nachricht an Client B. Brauche ich also eine weitere Liste in der die Nachrichten gesammelt werden und dann weiter geleitet werden? Quasi: Client A - an Server - Server an Liste - Timer (ect.?) Durchläuft liste und sendet an alle Clienten - oder wie mache ich das sonst?

Gruß
paD
 
Zuletzt bearbeitet:

String

Erfahrenes Mitglied
Ok, List klappt schonmal soweit.

Aber nun wieder ein Problem:
Client eigenschaften? Wie löse ich das? Z.b. Namen, Positionen, oder auch einfach nur eine Farbe.

In dieser List kann ich ja quasi nur die Streams speicher oder sehe ich das falsch?

Sagen wir mal ich will name, farbe und den Stream eines Users "speichern/verwalten"
Wie mache ich das dann?
 

Alexander Schuc

crazy-weasel
Erstelle eigene Klasse, welche für die direkte Kommunikation mit den Clients verantwortlich sind.

Wenn ein neuer Client verbindet (nach AcceptTcpClient) erstellst du eine Instanz der Klasse, übergibst dieser den TcpClient, und beim Erstellen des Threads gibst eine Methode dieses Objekts an.

Dann speicherst dieses Objekt in einer Liste, und bist ansich fertig mit diesem einen Client, und kannst auf den nächsten Thread warten.

Lies das nochmal. ;)

Ich meinte noch eine eigene zusätzliche Klasse, wo jeder Client eine eigene Instanz davon bekommt. Mit der kannst du dann die Daten zu jedem Client verwalten, und in der Liste speicherst auch diese Instanzen..
 

String

Erfahrenes Mitglied
AAAHHH jetzt verstehe ich (glaube ich)

Also Klasse Clienten:
- Hier wird alles gespeichert // Name, Farbe, Position ect.
- Funktionen zum Lesen und Schreiben

Liste:
- Hier wird quasi die "klassen-Instanz" als Objekt gespeichert

Thread:
- An dem Thread wird also die Klassen-Instanz geleitet.
- Dieser Liest und Schreibt ggb. die Streams

Verstehe ich das richtig? Oder habe ich jetzt immernoch einen Denkfehler?

Noch eine Frage: Wie speichere ich die Klassen-Instanz in der Liste?
Code:
Dim clients As New List(Of Object)

....
// Bei Clientverbindung
Dim neuerClient as new Client(ServerAcceptTcpClient())
Clients.Add(neuerClient)
- Thread starten, der die Klasse weiterhin verarbeitet..

Public Class Client
    Dim stream As NetworkStream
    Dim name As String
     .. usw...

    Sub New(ByVal cstream As NetworkStream)
        s...
    End Sub
End Class
Ist das soweit richtig? Wenn ja, wie kann ich denn einen Clienten nachher wieder löschen. Daher ich einfach nur Clients.Add(neuerClient) speichere, kann ich nachher nicht mit Clients.Remove() arbeiten oder?
 

Alexander Schuc

crazy-weasel
Die Liste kannst ruhig mit "List (of Client)" erstellen, immerhin willst ja Client-Objekte drin speichern.

Natürlich kannst mit Remove die Objekte aus der Liste entfernen.

Bei so Sachen wo du eine Theorie hast, dir aber nicht sicher bist.. probiers doch einfach aus. Da merkst dann ja oft von selbst, obs geht oder nicht. ;)
 

String

Erfahrenes Mitglied
Bestens =) =) =)

Jetzt läuft alles soweit.
Leider tritt nun ein ganz anderer Fehler auf:

100 % CPU belastung, sobald ein Client connectet.

Hast du ne Idee, woran das liegt?
 
Zuletzt bearbeitet:

Alexander Schuc

crazy-weasel
Deine "Lesen"-Methode liest nicht vom Stream. Deswegen blockiert da auch nichts, und die Schleife rennt munter vor sich hin. Deswegen hast 100% CPU Last.
 

Neue Beiträge