[VB .Net 2005] Anzahl der Verbindungen begrenzen bei TcpClient und/oder Socket

calvin65

Mitglied
Hallo liebe Leute,

ich habe da ein Problem mit TcpClient und Socket.
Das ganze soll so ähnlich laufen wie ein Chat-Programm, mit jeweils einem Client am Port - aber auch nur einem, d.h., dass nach dem Ende der Verbindung sich kein anderer mehr anstellen kann. Daher wurde Listen schon auf 0 gesetzt. Das Problem besteht aber weiterhin. Momentan wird ein Teststring übermittelt und am Server in einer Textbox angezeigt.
Also nach dem Motto:
Server macht Port 8000 auf und wartet auf Verbindung
Client1 verbindet sich und übermittelt Nachrichten und diese werden angezeigt
Client2 klopft an, kann aber momentan nicht übermitteln (wenn ers dennoch versucht wird aber alles gespeichert)
Client1 trennt Verbindung + alle Daten welche Client2 gesendet hat werden sichtbar

Code:
zum Verbinden:
Dim oServerSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP)
Dim oClientSocket As Socket
Dim oIPAddress As IPAddress

If (oIPAddress Is Nothing) Then
            Dim ipHost As IPHostEntry = Dns.GetHostEntry(Dns.GetHostName())
            oIPAddress = ipHost.AddressList(0)
            nPort = 8000
         End If
         Dim localEP As New IPEndPoint(oIPAddress, nPort)

         oServerSocket.Bind(localEP)
         oServerSocket.Listen(0)

zum Empfangen:
         oClientSocket = oServerSocket.Accept
         Empfang ....

zum Trenen:
oClientSocket.Blocking = False
         If Not (oServerSocket Is Nothing) Then oServerSocket.Listen(0)

         'Server schließen
         If Not (oServerSocket Is Nothing) Then
            If oServerSocket.Connected Then oServerSocket.Disconnect(False)
            oServerSocket.Close(5)
            oServerSocket = Nothing
         End If

Daher die Frage: Wie kann ich eine maximale Anzahl an Verbindungen für diesen Socket einstellen?

MaxConnections steht zwar in der MSDN, gibts aber nicht:
Wird nicht unterstützt. Löst bei Verwendung eine SocketException aus.

Danke schonmal.
MfG Calvin
 
Zuletzt bearbeitet:
Hi!

Deine Problemstellung widerspricht sich. Wie sollen die Nachrichten des 2. Clients gespeichert werden, wenn Du keine mehrfache Connection auf den einen Port zulassen möchtest?
Du müsstest dem 2. Client in deinem Verbindungsprotokoll mitteilen, dass bereits eine Verbindung aktiv ist. Entweder Du disconnectest ihn oder Du lässt ihn warten und speicherst alles was er danach noch sendet. Deine Clients legst am besten in einer Liste mit der Zeit ab wann sie sich connected haben. Dann kannst alles in genau der Reihefolge abarbeiten.
 
Das widerspricht sich eigentlich nicht.
Also: Im Test mit 2 einfachen Clients die einfach nur Daten senden konnten war eindeutig zu sehen, dass die vom 2. Client übertragenen Daten gespeichert wurden und dann angezeigt werden, wenn Client1 weg ist.

Es soll eigentlich so sein:
Server lauscht
Client1 verbindet sich und sagt: "Hier darf kein weiterer dran"
Client2 versucht sich zu verbinden, wird aber (automatisch) abgewiesen
Client1 trennt und sagt: "Jetzt kann jemand"
Client2 kann sich verbinden

Code:
If Not oServerSocket.Connected Then
                  connect....
            else
                 nix
            end if
brachte auch nichts, da jeweils nur ein Client dran war.
Client1 hat sich verbunden und übertragen, währenddessen wurde Client2 aktiviert, hat aber KEINE Ablehnung erhalten und konnte auch übertragen (besser gesagt in seinen eigenen Puffer schreiben).
Trennt man nun Client1, so verbindet Client2 sich und schickt seine Daten.

Ich kann leider nicht immer garantieren, dass sich auf diesen Port nur mein Client dranhängen will und daher ist eine porgramminterne Ablehnung zwischen Client und Server sinnlos.
Ich brauche schon sowas wie "MaxConnections", was ich auf 1 setzen kann und alle anderen Programme, die sich nach dem 1. verbinden wollen automatisch ablehnt.
Ich werde auch eine Authentifizierung machen müssen, aber trotzdem wird mir der Eingabepuffer gefüllt und das soll ja nicht sein.
MfG Calvin
 
Du verwendest anscheinend ein und den selben Socket, daher werden die Daten des 2. Clients auch geblockt. Verwende daher den TcpListener den Du immer wieder nach neuen Verbindungen abfragst und erstelle einen neuen Socket für einen neu gefundenen Client. Mit Socket.Bind( EndPoint ) kannst deinen Client dann an diesen Binden.
Wenn sich wieder ein neuer Client connected hat, kannst diesen dann wiederum in einem neuen Socketobjekt direkt verwalten, sprich einfach disconnecten oder seine Daten simultan abrufen.
 
Danke, das hört sich schonmal recht gut an. Dann wäre ja nur noch die Frage: Wie?

Ich verwende ja die Instanz der Klasse clsServer.

Darin gibts dann Initialisieren, also binden des Server an den Socket.
Code:
oServerSocket.Bind(localEP)
oServerSocket.Listen(0)

Dann das asynchrone Starten des eigentlichen Servers, also Client an seinen Socket binden [mit clientsocket.accept()] und das zuhören und das zusammen läuft asynchron ab. Und wenn es darin Daten gibt fliegen die mit einem Event raus.
Code:
oClientSocket = oServerSocket.Accept
Do While oClientSocket.Connected
      nLength = oClientSocket.Receive(nData)
      If nLength > 0 Then RaiseEvent NewData(nData)
Loop

Wenn ich dich richtig verstanden habe soll das oClientSocket = oServerSocket.Accept gegen ein listener.acceptsocket oder .accepttcpclient eingetauscht werden.
Aber wie kann ich da dann immer gleichzeitig auf mehreren Sockets nach Verbindungen suchen und diese binden/abweisen?
 
Leider habe ich im Moment nicht viel Zeit dir ein Beispiel dazu zu machen. :(
Dem TcpServer und dem TcpListener liegt ein Socket zugrunde. Diese Objekte vereinfachen es einem lediglich, einen Socket als Client oder Server verwenden zu können. Willst ganz spezielle Aufgaben bewältigen, muss den Socket selber verwalten....

Ich hätte aber für ein paar Themen, aus denen Du dir alle nötigen Informationen ziehen kannst. :)
  • [thread=241988]Multi-Client mit TCPListener und TCPClient - Thread[/thread]
  • [thread=261363]TCPListener empfängt nur 1 mal etwas, obwohl handleClient. Fehler suche. - Thread (C#)[/thread]
 
Danke für die Threads, hatte ich aber auch schon selber gefunden. :)
Hab mit jetzt das asynchrone auf Backgroundworker gelegt, ist wenigstens einfacher. Das Problem besteht aber immer noch. Wenn sich ein Client anmeldet und ein zweiter hinterher, dann verbindet sich der 2. automatisch, wenn der 1. weg ist.

Dann ist bei mir aber auch noch ein 2. Problem aufgetaucht. Ich brauche auch noch einen Client, der sich gleichzeitig mit mehreren Servern verbinden kann.
Ich denke mal es könnte so gehen: für jeden Server wird ein eigener Backgroundworker aufgemacht, in welchem je auf eine Verbindung zum Server auf Nachrichten gewartet wird, bzw. welche an den Server gesendet werden.
Welche Möglichkeit besteht denn, dass das so in etwa funktioniert? Irgendeine Idee?
 
Danke für die Threads, hatte ich aber auch schon selber gefunden. :)
Hab mit jetzt das asynchrone auf Backgroundworker gelegt, ist wenigstens einfacher. Das Problem besteht aber immer noch. Wenn sich ein Client anmeldet und ein zweiter hinterher, dann verbindet sich der 2. automatisch, wenn der 1. weg ist.
Wie hast es denn jetzt realisiert? Hab doch gesagt einen neuen Socket für jede neue Verbindung erstellen und an den EndPoint des Clients an den Socket binden. Somit bleibt der TcpListener Socket immer frei für neue Verbindungsanforderungen.

Dann ist bei mir aber auch noch ein 2. Problem aufgetaucht. Ich brauche auch noch einen Client, der sich gleichzeitig mit mehreren Servern verbinden kann.
Ich denke mal es könnte so gehen: für jeden Server wird ein eigener Backgroundworker aufgemacht, in welchem je auf eine Verbindung zum Server auf Nachrichten gewartet wird, bzw. welche an den Server gesendet werden.
Welche Möglichkeit besteht denn, dass das so in etwa funktioniert? Irgendeine Idee?
Du musst jede einzelne Verbindung als Session abstrahieren um sie besser verwalten zu können. Wenn wenn Du das ganze asynchron implementierst, was in dem Szenario empfehlenswert ist, sparst Du dir den Backgroundworker. Jede asynchrone Ereignisbehandlung wird dabei immer in einem separaten Thread ausgeführt, da musst die Ereignisse aber wiederum entsprechend Synchronisieren, was eigentlich nicht so schwer sein sollte, sofern man sich da hinein gefuchst hat. :)

Mach Dir lieber Gedanken über ein gescheites und funktionales Protokoll. ;) Apropos, Remoting kommt für dich wohl nicht in Frage? Ich meine, wenn Du nur mit .NET Mitteln auf beiden Seiten arbeitest, würde das den Implementationsaufwand erheblich verkleinern...
 

Neue Beiträge

Zurück