<p>我是django websocket的作者。我不是一个真正的专家,在网站和网络的话题,但我认为我有一个体面的理解正在发生的事情。抱歉,我说得太详细了。即使大多数答案不是针对你的问题的,它也可能在其他方面对你有所帮助。:-)</p>
<hr/>
<h2>websockets的工作原理</h2>
<p>让我简单地解释一下websocket是什么。websocket从一个看起来像是从浏览器建立的普通HTTP请求开始。它通过一个HTTP报头表示它希望将协议“升级”为websocket,而不是HTTP请求。如果服务器支持websockets,则它同意握手,并且服务器和客户端现在都知道它们将使用以前用于HTTP请求的已建立的tcp套接字作为交换websocket消息的连接。</p>
<p>除了发送和等待消息之外,它们当然还可以随时关闭连接。</p>
<h2>django websocket如何滥用python的wsgi请求环境来劫持套接字</h2>
<p>现在让我们详细了解一下django websocket如何在django请求-响应循环中实现HTTP请求的“升级”。</p>
<p>Django通常使用WSGI规范与apache或gunicorn等web服务器进行通信。该规范是在考虑到HTTP非常有限的通信模型的情况下设计的。它假设它获得一个HTTP请求(仅传入数据)并返回响应(仅传出数据)。这使得将django强制引入允许双向通信的websocket概念变得很棘手。</p>
<p>为了实现这一点,我在django websocket中所做的是深入研究WSGI和django的请求对象的内部,以检索底层套接字。然后使用这个tcp套接字直接将HTTP请求升级到websocket实例。</p>
<p><strong>现在回答您原来的问题…</strong></p>
<p>我希望上面清楚地表明,当websocket建立时,返回HttpResponse是没有意义的。这就是为什么通常不返回由django websocket处理的视图中的任何内容。</p>
<p>不过,我想紧跟视图的概念,视图保存逻辑并根据输入返回数据。这就是为什么您应该只使用视图中的代码来处理websocket。</p>
<p>从视图返回后,websocket将自动关闭。这样做是有原因的:我们不想让套接字在一段未定义的时间内保持打开,并且依赖客户端(浏览器)来关闭它。</p>
<p>这就是为什么不能在视图之外访问带有django websocket的websocket。文件描述符当然被设置为-1,表示它已经关闭。</p>
<h2>免责声明</h2>
<p>我在上面解释过,我正在django的周围环境中进行挖掘,以某种方式——以一种非常黑客的方式——访问底层套接字。这是非常脆弱的,也不应该工作,因为WSGI不是为这个设计的!我在上面还解释过,websocket在视图结束后关闭——然而,在websocket关闭(并关闭tcp套接字)之后,django的WSGI实现尝试发送HTTP响应——它不知道websocket s,并认为它处于正常的HTTP请求-响应周期。但是套接字已经关闭,发送将失败。这通常会导致django中出现异常。</p>
<p>这并没有影响我对开发服务器的测试。浏览器永远不会注意到(你知道。。套接字已经关闭;-)-但是在每个请求中引发一个未处理的错误不是一个很好的概念,并且可能会泄漏内存,无法正确处理数据库连接关闭,并且如果您使用django websocket进行更多的实验,那么很多athor事件在某个时刻都会中断。</p>
<p>这就是为什么我真的建议你不要使用websocket我们还有django</em></strong>呢。它不是故意的。Django,特别是WSGI,需要进行全面的检查来解决这些问题(参见<a href="http://groups.google.com/group/paste-users/browse_thread/thread/2f3a5ba33b857c6c" rel="noreferrer">this discussion for websockets and WSGI</a>)。从那时起,我建议使用类似<a href="http://eventlet.net/" rel="noreferrer">eventlet</a>的方法。Eventlet有一个工作的websocket实现(我从Eventlet为django websocket的初始版本借用了一些代码),由于它只是简单的python代码,所以您可以从django导入模型和其他所有东西。唯一的缺点是需要另一个运行的webserver来处理websockets。</p>