Ich bin der Autor von Django-Websocket. Ich bin kein echter Experte in Sachen Websockets und Networking, aber ich denke, ich habe ein gutes Verständnis davon, was los ist. Tut mir leid, dass ich ins Detail gegangen bin. Auch wenn der Großteil der Antwort nicht spezifisch für Ihre Frage ist, könnte es Ihnen an einem anderen Punkt helfen. :-)
Wie WebSockets
arbeiten
mich kurz Lassen Sie erklären, was ein websocket ist. Ein Websocket startet als etwas, das wirklich wie eine einfache HTTP-Anfrage aussieht, die vom Browser aus erstellt wird. Es zeigt über einen HTTP-Header an, dass es das Protokoll als Websocket "upgraden" will, statt als HTTP-Anfrage. Wenn der Server Websockets unterstützt, stimmt er dem Handshake zu und beide - Server und Client - wissen nun, dass sie den etablierten tcp-Socket, der früher für die HTTP-Anfrage verwendet wurde, als Verbindung zum Austausch von Websocket-Nachrichten verwenden.
Neben dem Senden und Warten auf Nachrichten haben sie natürlich auch die Möglichkeit, die Verbindung jederzeit zu schließen.
Wie django-websocket Mißbräuche der wsgi Anfrage Umgebung Python die Buchse
Jetzt bekommen in die Details, wie django-websocket implementiert die "Aufwertung" der HTTP-Anforderung in einer django Request-Response cylce lässt kapern.
Django verwendet normalerweise die WSGI-Spezifikation, um mit dem Webserver wie Apache oder Gunicorn usw. zu kommunizieren. Diese Spezifikation wurde nur mit dem sehr eingeschränkten Kommunikationsmodell von HTTP entworfen. Es wird davon ausgegangen, dass es eine HTTP-Anforderung (nur eingehende Daten) erhält und die Antwort (nur ausgehende Daten) zurückgibt. Dies macht es schwierig, Django in das Konzept eines Websockets zu zwingen, wo bidirektionale Kommunikation erlaubt ist.
Was ich in django-websocket tun, um dies zu erreichen, ist, dass ich sehr tief in die Interna von WSGI und django Request-Objekt, um den Underlaying-Socket abrufen. Dieser tcp-Socket wird dann verwendet, um die HTTP-Anfrage direkt an eine Websocket-Instanz zu übertragen.
Nun zu Ihrer ursprünglichen Frage ...
ich hoffe, die oben macht es offensichtlich, dass, wenn ein websocket hergestellt ist, hat es keinen Sinn ein Httpresponse bei der Rückkehr. Aus diesem Grund geben Sie normalerweise in einer Ansicht, die von django-websocket gehandhabt wird, nichts zurück.
Allerdings wollte ich nah an dem Konzept einer Sicht halten, die die Logik hält und Daten basierend auf der Eingabe zurückgibt. Aus diesem Grund sollten Sie nur den Code in Ihrer Sicht verwenden, um den Websocket zu handhaben.
Nachdem Sie von der Ansicht zurückgekehrt sind, wird der Websocket automatisch geschlossen. Dies geschieht aus einem bestimmten Grund: Wir möchten den Socket nicht für eine unbestimmte Zeit offen halten und verlassen uns auf den Client (den Browser), um ihn zu schließen.
Aus diesem Grund können Sie auf einen Websocket mit django-websocket außerhalb Ihrer Sicht nicht zugreifen. Der Dateideskriptor wird dann natürlich auf -1 gesetzt, um anzuzeigen, dass er bereits geschlossen ist. in einer sehr hackish Weise - - Zugriff auf die darunter liegende Buchse irgendwie zu bekommen
Haftungsausschluss
ich darüber erklärte ich in der Umgebung von django zu graben. Dies ist sehr fragil und sollte auch nicht funktionieren, da WSGI nicht dafür gedacht ist! Ich habe auch oben erklärt, dass der Websocket geschlossen wird, nachdem die Ansicht endet - aber nachdem die WebSocket geschlossen wurde (UND den TCP-Socket geschlossen hat), versucht djangos WSGI-Implementierung eine HTTP-Antwort zu senden - sie weiß nichts über WebSockets und denkt, dass sie da ist ein normaler HTTP-Anfrage-Antwort-Zyklus. Aber der Socket ist bereits geschlossen und das Senden wird fehlschlagen. Dies verursacht normalerweise eine Ausnahme im Django.
Das hat meine Tests mit dem Entwicklungsserver nicht beeinflusst. Der Browser wird es nie bemerken (Sie wissen, dass der Socket bereits geschlossen ist ;-)), aber ein unbehandelter Fehler in jeder Anfrage anzuwerfen ist kein sehr gutes Konzept und kann Speicher verlieren, nicht korrektes Herunterfahren der Datenbankverbindung und viele andere Dinge dass wird brechen an einem bestimmten Punkt, wenn Sie Django-Websocket für mehr als das Experimentieren verwenden. Diese
Deshalb würde ich Sie wirklich raten nicht WebSockets mit django noch zu verwenden. Es funktioniert nicht mit Absicht. Django und speziell WSGI würden eine Totalüberholung benötigen, um diese Probleme zu lösen (siehe this discussion for websockets and WSGI). Seitdem würde ich vorschlagen, etwas wie eventlet zu verwenden.Eventlet hat eine funktionierende Websocket-Implementierung (ich habe etwas Code von eventlet für die erste Version von django-websocket ausgeliehen) und seit seinem einfachen Python-Code können Sie Ihre Modelle und alles andere von django importieren. Der einzige Nachteil ist, dass Sie einen zweiten Webserver benötigen, der nur für den Umgang mit Websockets läuft.
@EliCourtwright Sie haben das Kopfgeld nicht vergeben .. – pradyunsg
@paddila: Ja, es lässt Sie 24 Stunden warten, auch wenn der Grund für die Eröffnung der Bounty ist "Eine oder mehrere der Antworten ist vorbildlich und würdig zusätzliches Kopfgeld. " Ich werde das Kopfgeld vergeben, sobald das System mich lässt. –