Ich schreibe ein Client-Server-Paar in C ++ mit Linux-Sockets. Ich möchte, dass der Server auf eine Verbindung wartet, und während ein Client verbunden ist, sollte der Server alle anderen Clients ablehnen, die versuchen, eine Verbindung herzustellen.
Ich habe versucht, dies zu implementieren, indem ich den Backlog-Parameter in der listen -Funktion auf 0 und auf 1 und keines einstellte dieser Werte scheint zu funktionieren. Der erste Client verbindet sich wie erwartet, aber alle nachfolgenden Clients blockieren gerade, während der erste Client beendet ist. Was für mich wirklich verwirrend ist, ist, dass sie die Verbindung zum Server nicht blockieren, sondern beim ersten Lesen blockieren.
Ich habe den Code hier verwendet, um mit dem Schreiben meines Clients und Servers zu beginnen. Weiß jemand, was ich ändern muss, damit der Server nur eine Client-Verbindung akzeptiert und alle weiteren Verbindungsversuche abbricht?
Wenn Sie eine Verbindung akzeptieren, wird ein neuer Socket erstellt. Der alte wird immer noch verwendet, um auf zukünftige Verbindungen zu hören.
Da Sie nur eine Verbindung gleichzeitig zulassen möchten, können Sie einfach die Verbindungen akzeptieren und dann den neuen akzeptierten Socket schließen, wenn Sie feststellen, dass Sie bereits eine andere Verbindung verarbeiten.
Gibt es einen Nettounterschied, den Sie suchen, verglichen mit dem Schließen der neuen akzeptierten Steckdose direkt nach dem Akzeptieren? Der Client wird es wissen, sobald er versucht, seinen Socket zu verwenden (oder sofort, wenn er bereits auf dem Server mit einem Leseaufruf wartet) mit einem letzten Fehler: Server hat die Verbindung aktiv geschlossen.
Nur nicht fork()
nach accept()
.
Dieser Pseudo-C-Code akzeptiert nur einen Client gleichzeitig.
%Vor%Sie können Ihren ursprünglichen Socket schließen, der nach Annahme der ersten Verbindung auf Verbindungen wartet. Ich weiß nicht, ob die von Ihnen verwendete Socket-Klasse dies erlaubt.
Klingt so, als müssten Sie es manuell implementieren. Lassen Sie einen Client eine Verbindung herstellen, und senden Sie eine Trennungsnachricht vom Server an den Client, wenn bereits ein anderer Client verbunden ist. Wenn der Client diese Nachricht erhält, trennen Sie die Verbindung.
Da Sie nur eine Verbindung gleichzeitig zulassen möchten, können Sie einfach die Verbindungen akzeptieren und dann den neuen akzeptierten Socket schließen, wenn Sie feststellen, dass Sie bereits eine andere Verbindung verarbeiten.
Ich denke, es sollte die Horchbuchse sein, die geschlossen werden soll. Wenn die erste Verbindung hergestellt ist, schließen Sie den ursprünglichen Abhör-Socket. Und danach können keine weiteren Verbindungen hergestellt werden.
Nachdem die erste Verbindung beendet ist, können Sie einen neuen Socket zum erneuten Abhören erstellen.
Wenn Sie die Kontrolle über die Clients haben, können Sie die Sockets nicht blockieren. In diesem Fall geben sie die Fehlermeldung EINPROGRESS
zurück.
Ich bin immer noch auf der Suche nach dem Ändern des Sockets nicht blockierend sein. Wenn jemand weiß, wie man aus der Hand geht, können Sie die Antwort bearbeiten.
Möglicherweise haben Sie die Socket-Option TCP_DEFER_ACCEPT
auf Ihrem hörenden Socket:
Ich nehme an, es würde zu dem von Ihnen beschriebenen Effekt führen, dass der verbindende Client nicht auf dem connect
, sondern auf dem nachfolgenden read
blockiert. Ich bin nicht genau sicher, was ist die Option Standardeinstellung und was sollte eingestellt werden, um dieses Verhalten zu deaktivieren, aber wahrscheinlich ist ein Wert von Null einen Versuch wert:
Soweit ich sehe, ist es nicht möglich, genau eine Verbindung zu hören.
Tcp beinhaltet einen 3-Wege-Handshake. Nachdem das erste syn
Paket empfangen wurde, stellt der Kernel diese "Verbindung" in eine Warteschlange, antwortet mit einem syn/ack
und wartet auf den letzten ack
. Nachdem dies empfangen wurde, verschiebt es die Verbindung von der Warteliste zur Annahmewarteschlange, wo sie von der Anwendung mit dem accept()
-Aufruf abgeholt werden kann. (Details dazu finden Sie hier .)
Unter Linux limitiert das Backlog-Argument nur die Größe der Accept-Queue. aber der Kernel wird immer noch die 3-Wege-Handshake-Magie machen. Der Client empfängt syn / ack und antwortet mit der letzten Bestätigung und ruft die Verbindung auf.
Sie haben nur die Wahl, entweder den abhörenden Anschluss zu beenden, sobald Sie die erste Verbindung akzeptiert haben. (Dies kann jedoch dazu führen, dass bereits andere Verbindungen verfügbar sind.) Oder Sie nehmen andere Verbindungen aktiv an und schließen sie sofort, um den Client zu benachrichtigen.
Die letzte Option, die Sie haben, ist diejenige, die Sie bereits verwenden: Lassen Sie den Server Ihre Verbindungen in eine Warteschlange stellen und sie nacheinander verarbeiten. Ihre Kunden werden in diesem Fall blockieren.