2012-05-18 15 views
34

Zuerst muss ich fragen, welches ist das beste in welchen Staaten? Zum Beispiel ein Echtzeit-MMORPG-Server. Was passiert, wenn ich einen Thread pro Client anstelle von nicht blockierenden Sockets erzeuge? Oder Was, wenn ich einen Thread verwende, der alle nicht blockierenden Sockets enthält? Kannst du mir die Vorteile erklären?Warum sollte ich nicht blockierende oder blockierende Sockets verwenden?

Antwort

29

Ihre Frage verdient eine viel längere Diskussion, aber hier ist ein kurzer Stich in einer Antwort:

  • mit blockierende Sockets bedeutet, dass nur eine Steckdose jederzeit in einem Thread aktiv sein kann (weil es blockiert während des Wartens für die Aktivität)
  • mit blockierende Sockets ist in der Regel einfacher, als nicht-blockierende Sockets (asynchrone Programmierung neigt kompliziertere)
  • Sie 1 Faden könnten pro Socket sein erstellen, wie Sie erwähnten aber Threads Overhead und ist extrem ineffizient im Vergleich zu dem nicht blockierende Lösungen;
  • mit nicht-blockierenden Buchsen können Sie ein viel größeres Volumen von Kunden behandeln: es Hunderttausende in einem einzigen Prozess skalieren konnte - aber der Code wird ein wenig komplizierte

Mit nicht-blockierende Sockets (unter Windows) Sie haben ein paar Optionen:

  • Polling
  • Ereignisse basierend
  • I überlappt/O

Überlappte E/A bietet Ihnen die beste Leistung (Tausende von Sockets/Prozess) auf Kosten von das komplizierteste Modell zu verstehen und korrekt zu implementieren.

Im Grunde geht es um die Leistung im Vergleich zur Komplexität der Programmierung.

HINWEIS

Hier ist eine bessere Erklärung, warum Modell eines Gewinde/Buchse verwendet, ist eine schlechte Idee:

In Windows ist eine große Anzahl von Threads zu schaffen höchst ineffizient, weil der Scheduler nicht in der Lage ist Stellen Sie fest, welche Threads die Prozessorzeit erhalten sollen und welche nicht. Zusammen mit dem Speicheraufwand jedes Threads bedeutet dies, dass Ihnen auf Betriebssystemebene nicht genügend Arbeitsspeicher (wegen Stapelspeicherplatz) und Prozessorzyklen (wegen Overhead bei der Verwaltung von Threads) zur Verfügung steht, bevor Ihnen die Kapazität zum Behandeln von Socketverbindungen ausgehen wird .

+0

Wenn Sie auf einem 80-Wege-Box laufen lassen, können Sie Hunderte von Threads kein Problem herausreißen. –

+0

@John - Nur weil es möglich ist, Hunderte von Threads zu erstellen (wenn Sie genug Speicher haben), bedeutet das nicht, dass es eine gute Idee ist. In der Tat ist es eine schlechte Idee! –

+9

Mein Punkt, zugegebenermaßen nicht gut gemacht, ist, dass Sie nicht einfach eine willkürliche Zeile bei 20 zeichnen und eine beliebige Anzahl von Threads darüber hinaus "schlecht" aufrufen können. –

8

Ich werde auf der Platte als sagen, dass für fast alles außer Spielzeug-Programme, sollten Sie nicht blockierende Sockets als selbstverständlich zu gehen.

Das Blockieren von Sockets verursacht ein schwerwiegendes Problem: Wenn der Computer am anderen Ende (oder an einem Teil davon) während eines blockierenden Anrufs ausfällt, wird Ihr Code bis zum Timeout des IP-Stacks blockiert. In einem typischen Fall sind das ungefähr 2 Minuten, was für die meisten Zwecke völlig inakzeptabel ist. Der einzige Weg abzubrechen, ist das Beenden des Threads, der es gemacht hat - aber das Beenden eines Threads ist selbst fast immer inakzeptabel, da es im Grunde unmöglich ist, danach aufzuräumen und alle ihm zugewiesenen Ressourcen wiederzugewinnen.Nicht-blockierende Sockets machen es trivial, einen Anruf abzubrechen, wenn/ohne irgendetwas tun, um den Thread, der den Anruf gemacht hat.

Es ist möglich, blockierende Sockets funktionieren gut zu machen Wenn Sie stattdessen ein Multi-Prozess-Modell verwenden. Hier spawnen Sie einfach für jede Verbindung einen völlig neuen Prozess. Dieser Prozess verwendet einen blockierenden Socket, und wenn etwas schief geht, bringst du einfach den gesamten Prozess um. Das Betriebssystem weiß, wie die Ressourcen von einem Prozess bereinigt werden, so dass die Bereinigung kein Problem darstellt. Es hat jedoch noch andere potentielle Probleme: 1) Sie benötigen einen Prozessmonitor, um Prozesse bei Bedarf zu beenden, und 2) einen Prozess zu erzeugen ist normalerweise ein bisschen teurer als nur einen Socket zu erstellen. Dennoch kann dies eine sinnvolle Option sein, vor allem, wenn:

  1. Sie sind im Allgemeinen zu einer Zeit
  2. Sie tun umfangreiche Verarbeitung mit einer geringen Anzahl von Verbindungen zu tun nur für jede Verbindung
  3. Sie es zu tun mit lokalen Hosts, um sie so Ihre Verbindung ist schnell und zuverlässig
  4. Sie sind mehr mit der Entwicklung der Optimierung als Ausführung

1. Nun, technisch nicht die nur möglichen Weg, aber die meisten Alternativen sind relativ hässlich - um genauer zu sein, ich denke, bis Sie Code hinzufügen, um herauszufinden, dass es ein Problem gibt, und dann Behebe das Problem, du hast wahrscheinlich mehr Arbeit geleistet, als wenn du nur einen nicht blockierenden Socket benutzt.

+6

Es ist möglich, einen blockierten Socket-Vorgang abzubrechen, ohne den blockierten Thread zu beenden, indem Sie den Socket von einem anderen Thread-Kontext trennen. Das führt dazu, dass die blockierte Operation mit einem Fehlercode fehlschlägt, dann kann der blockierte Thread weitergehen und andere Dinge tun, wie normale Bereinigung. –

Verwandte Themen