当前位置: 首页 > 面试题库 >

带websockets和python / django(/扭曲?)

曾宏毅
2023-03-14
问题内容

websockets有趣的部分是从服务器向浏览器发送本质上未经请求的内容,对吗?

好吧,我正在使用GregorMüllegger的django-websocket。使Websockets在Django中工作确实是一个很棒的早期尝试。

我完成了“ helloworld”。它的工作方式是:当请求是websocket时,会将对象websocket附加到请求对象。因此,在解释websocket的视图中,我可以执行以下操作:

request.websocket.send('We are the knights who say ni!')

很好 我在浏览器中收到的消息像超级按钮一样。

但是,如果我不想在没有浏览器发出请求的情况下这样做呢?

OK,所以首先我将websocket保存在会话字典中:

request.session['websocket'] = request.websocket

然后,在外壳中,我按会话密钥获取会话。当然,会话字典中有一个websocket对象。快乐!

但是,当我尝试执行以下操作时:

>>> session.get_decoded()['websocket'].send('With a herring!')

我得到:

Traceback (most recent call last):
File "<console>", line 1, in <module>
error: [Errno 9] Bad file descriptor

伤心。:-(

好的,所以我对套接字一无所知,但是我知道足以在调试器中四处嗅探,瞧瞧,我看到了调试器中的套接字(与请求中的真正websocket绑定在一起)有fd =6,而我从会话保存的Websocket中抢到的那个有fd = -1。

面向套接字的人可以帮助我解决这些问题吗?


问题答案:

我是django-
websocket的作者。我不是Websocket和网络领域的真正专家,但是我认为我对所发生的事情有很好的了解。对不起,我很详细。即使大多数答案不是特定于您的问题,也可能会在其他时候为您提供帮助。:-)

让我简短地解释一下什么是websocket。Websocket的启动看起来像是一个简单的HTTP请求,是通过浏览器建立的。它通过HTTP标头指示它希望将协议“升级”为Web套接字而不是HTTP请求。如果服务器支持websocket,则表示同意握手,并且服务器和客户端现在都知道它们将使用以前用于HTTP请求的已建立tcp套接字作为连接来交换websocket消息。

除了发送和等待消息外,他们当然还具有随时关闭连接的能力。

django-websocket如何滥用python的wsgi请求环境来劫持套接字

现在,让我们详细了解django-websocket如何在django请求-响应网络中实现HTTP请求的“升级”。

Django通常使用WSGI规范来与Web服务器通信,例如apache或gunicorn等。该规范的设计仅考虑到HTTP的通信模型非常有限。它假定它获取一个HTTP请求(仅传入数据)并返回响应(仅传出数据)。这使得将django强制引入允许双向通信的websocket的概念非常棘手。

我在django-
websocket中为实现此目的而做的是,我非常深入地研究了WSGI的内部和django的请求对象以检索底层套接字。然后,此tcp套接字用于直接处理将HTTP请求升级到websocket实例。

现在到您的原始问题…

我希望以上内容可以使我们很明显,当建立一个websocket时,没有必要返回HttpResponse。这就是为什么通常在django-
websocket处理的视图中不返回任何内容的原因。

但是,我想坚持一个视图的概念,该视图包含逻辑并根据输入返回数据。这就是为什么您应该只在视图中使用代码来处理websocket的原因。

从视图返回后,websocket将自动关闭。这样做是有原因的:我们不想在不确定的时间内保持打开套接字的状态,而不必依靠客户端(浏览器)将其关闭。

这就是为什么您无法在视图外部使用django-websocket访问websocket的原因。然后,当然将文件描述符设置为-1,表明其已关闭。

免责声明

上面我解释说,我正在django的周围环境中进行挖掘,以某种方式-以一种非常骇俗的方式-
访问底层套接字。这非常脆弱,而且由于WSGI并非为此目的而设计,因此也不应该起作用!上面我还解释了视图结束后websocket是关闭的-但是,在websocket关闭(并关闭了tcp套接字)之后,django的WSGI实现尝试发送HTTP响应-它不知道websockets并认为它在正常的HTTP请求-响应周期。但是套接字已经关闭,发送将失败。这通常会在Django中引起异常

这并没有影响我对开发服务器的测试。浏览器永远不会注意到(您知道..套接字已经关闭;-)-但是在每个请求中引发未处理的错误不是一个很好的概念,并且可能会泄漏内存,无法正确处理数据库连接关闭以及许多麻烦的事情如果您使用django-
websocket进行更多的实验,那 在某些时候中断。

这就是为什么我会真正建议您 不要将Websocket与django一起使用的原因
。它不是设计使然。Django(尤其是WSGI)将需要进行全面改革以解决这些问题(有关Websockets和WSGI的信息,请参阅此讨论)。从那时起,我建议使用诸如eventlet之类的东西。Eventlet具有有效的websocket实现(我从eventlet借用了django-
websocket初始版本的一些代码),由于它只是纯Python代码,因此您可以从django中导入模型和其他所有内容。唯一的缺点是您需要第二个运行的Web服务器来处理websocket。



 类似资料:
  • 问题内容: websockets有趣的部分是从服务器向浏览器发送本质上未经请求的内容,对吗? 好吧,我正在使用GregorMüllegger的django-websocket。使Websockets在Django中工作确实是一个很棒的早期尝试。 我完成了“ hello world”。它的工作方式是:当请求是websocket时,会将对象websocket附加到请求对象。因此,在解释websocke

  • 问题内容: 谁能推荐一些简单的代码来使用Twisted设置简单的JSON RPC客户端和服务器? 我找到了txJSON-RPC,但我想知道是否有人对使用这些anc有一定的经验可以推荐一些东西。 问题答案: txJSONRPC很棒。我使用它,并且有效。我建议您尝试一下。 客户: 作为奖励,我将保留一些替代方案:放大器。 http://amp-protocol.net

  • 在客户端,我被迫使用socketio,因为浏览器支持的WebSocket不能与flask-socketio一起工作。总是这样,还是我做错了什么(这与问题2有关)。 到目前为止,我成功地在Flask调试模式下运行了Flask-socketio(python my_flask_source.py)。我阅读了Flask-socketio文档,了解到此模式不支持Websockets,只支持长轮询。事实上,

  • 问题内容: 因此,我研究了一些事情,包括使用python和Twisted框架编写HTTP代理。 本质上,像其他一些问题一样,我希望能够修改将发送回浏览器的数据。也就是说,浏览器请求资源,代理将获取资源。在资源返回浏览器之前,我希望能够修改ANY(HTTP标头和内容)内容。 这是我最初发现的(需要帮助编写扭曲的代理)。我尝试了一下,但对我没有用。我还发现了该功能(Python Twisted代理-

  • 我正在一个项目,有纯PHP作为后端和MySQL作为数据库。目前,我正在使用ajax来发布和接收来自数据库的数据。但我想使用Websockets的接收部分,使其实时。根据我的搜索和发现,人们引用Node.js、Redis PubSub等来实现它。然而,我没有找到一个关于这个主题的好教程。另外,据我所知,当我在后面运行复杂的PHP算法和MySQL查询时,Nods.js和PHP并不能很好地结合在一起。所

  • 我不确定这是否可以实现。我正在使用以下版本以群集模式运行docker: 客户端:版本:17.03.0-CE API版本:1.26Go版本:GO1.7.5 Git提交:3A232C8构建:周二2月28日08:10:07 2017 OS/arch:linux/amd64 显然,客户端套接字连接无法解析到群集中托管的服务集群。docker swarm是否有一个变通配置,或者它只是不可能?我没有太多的运气