鱼C论坛

 找回密码
 立即注册
查看: 3449|回复: 4

[已解决]求助Python Websocket+Django

[复制链接]
发表于 2023-4-20 15:34:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
按照各种教程的 setting routings类都配置完成 但是无法建立连接。后台报错Not found,网页里直接显示WebSocket connection to 'ws://127.0.0.1:8000/ws/wscon' failed:
对没错,他甚至不告诉我错误信息。
最佳答案
2023-4-22 10:17:36
根据您提供的代码和错误信息,可以看到Websocket连接请求的URL为ws://127.0.0.1:8000/ws/wscon。根据您提供的路由配置代码,Websocket连接请求应该匹配到URL为ws/(?P<websocket>\w+)/$的路由,并将请求的参数作为websocket传递给ChatConsumer类。

但是,您在路由配置代码中没有指定websocket参数的名称,导致chat_consumer.ChatConsumer.as_asgi()方法中无法解析该参数,因此出现了404 Not found错误。

为了解决这个问题,您需要将路由配置代码中的正则表达式修改为ws/(?P<websocket_name>\w+)/$,然后将websocket_name作为参数传递给ChatConsumer类。修改后的代码如下:
  1. websocket_urlpatterns = [
  2.     # 正则表达式创造websocket接口
  3.     re_path(r'ws/(?P<websocket_name>\w+)/$', chat_consumer.ChatConsumer.as_asgi())
  4. ]
复制代码

然后,在ChatConsumer类中,您需要将websocket_name参数传递给WebsocketConsumer的构造函数。修改后的代码如下:
  1. class ChatConsumer(WebsocketConsumer):
  2.     def __init__(self, *args, **kwargs):
  3.         super().__init__(*args, **kwargs)
  4.         self.websocket_name = self.scope['url_route']['kwargs']['websocket_name']

  5.     def websocket_connect(self, message):
  6.         print(f"连接已建立:{self.websocket_name}")
  7.         self.accept()

  8.     def websocket_receive(self, message):
  9.         self.send("不要回复不要回复")

  10.     def websocket_disconnect(self, message):
  11.         print(f"断开连接:{self.websocket_name}")
  12.         raise StopConsumer
复制代码

请注意,修改后的代码将websocket_name参数从URL中提取出来,并将其存储为ChatConsumer对象的一个属性。在websocket_connect和websocket_disconnect方法中,我们使用该属性来显示连接建立和断开的Websocket名称。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-20 15:37:40 | 显示全部楼层
以下是代码:
class ChatConsumer(WebsocketConsumer):

    # 客户端向服务器请求建立连接
    def websocket_connect(self, message):
        """
        有客户端向后台发送websocket连接请求时自动触发,服务器允许和客户端创建连接
        """
        print("连接已建立")
        self.accept()

    # 发送消息
    def websocket_receive(self, message):
        """
        浏览器基于websocket向后端发送数据,自动触发接收消息
        """
        self.send("不要回复不要回复")
        # 服务端主动断开连接
        # self.close()

    # 断开连接
    def websocket_disconnect(self, message):
        """
        客户端与服务器断开连接时,自动触发
        """
        print("断开连接")
        raise StopConsumer

application = ProtocolTypeRouter({
    'http': get_asgi_application(),  # 如果是http的请求就走这条
    'websocket': URLRouter(routings.websocket_urlpatterns),  # 如果是websocket就走这一条
})

# 创建路由所用文件
websocket_urlpatterns = [
    # 正则表达式创造websocket接口
    re_path(r'ws/(?P<websocket>\w+)/$', chat_consumer.ChatConsumer.as_asgi())
]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-20 15:43:26 | 显示全部楼层
根据您提供的代码,问题可能出现在websocket_urlpatterns中的正则表达式。尝试更新您的路由文件中的正则表达式,如下所示:
  1. websocket_urlpatterns = [
  2.     # 正则表达式创造websocket接口
  3.     re_path(r'ws/wscon/$', chat_consumer.ChatConsumer.as_asgi())
  4. ]
复制代码


这将确保您的WebSocket连接请求能够匹配正确的URL模式。

此外,确保您的Django项目的settings.py文件中已经添加了channels和相关的配置。这里是一个基本的示例配置:

  1. INSTALLED_APPS = [
  2.     # ...
  3.     'channels',
  4. ]

  5. # 设置Django默认的HTTP后端
  6. ASGI_APPLICATION = '<your_project_name>.asgi.application'

  7. # 设置channels配置
  8. CHANNEL_LAYERS = {
  9.     'default': {
  10.         'BACKEND': 'channels.layers.InMemoryChannelLayer',
  11.     },
  12. }
复制代码


确保您的Django项目根目录下有一个名为asgi.py的文件,它应该包含与您提供的相似的内容:

  1. import os
  2. from django.core.asgi import get_asgi_application
  3. from channels.routing import ProtocolTypeRouter, URLRouter
  4. import <your_app_name>.routings as routings
  5. from channels.auth import AuthMiddlewareStack

  6. os.environ.setdefault('DJANGO_SETTINGS_MODULE', '<your_project_name>.settings')

  7. application = ProtocolTypeRouter({
  8.     "http": get_asgi_application(),
  9.     "websocket": AuthMiddlewareStack(
  10.         URLRouter(
  11.             routings.websocket_urlpatterns
  12.         )
  13.     ),
  14. })
复制代码


确保将<your_project_name>替换为您的Django项目名称,将<your_app_name>替换为包含您的路由文件的应用名称。

如果您在尝试这些更改后仍然遇到问题,请提供更多详细信息,以便我们能够进一步帮助您解决问题。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-22 10:17:36 | 显示全部楼层    本楼为最佳答案   
根据您提供的代码和错误信息,可以看到Websocket连接请求的URL为ws://127.0.0.1:8000/ws/wscon。根据您提供的路由配置代码,Websocket连接请求应该匹配到URL为ws/(?P<websocket>\w+)/$的路由,并将请求的参数作为websocket传递给ChatConsumer类。

但是,您在路由配置代码中没有指定websocket参数的名称,导致chat_consumer.ChatConsumer.as_asgi()方法中无法解析该参数,因此出现了404 Not found错误。

为了解决这个问题,您需要将路由配置代码中的正则表达式修改为ws/(?P<websocket_name>\w+)/$,然后将websocket_name作为参数传递给ChatConsumer类。修改后的代码如下:
  1. websocket_urlpatterns = [
  2.     # 正则表达式创造websocket接口
  3.     re_path(r'ws/(?P<websocket_name>\w+)/$', chat_consumer.ChatConsumer.as_asgi())
  4. ]
复制代码

然后,在ChatConsumer类中,您需要将websocket_name参数传递给WebsocketConsumer的构造函数。修改后的代码如下:
  1. class ChatConsumer(WebsocketConsumer):
  2.     def __init__(self, *args, **kwargs):
  3.         super().__init__(*args, **kwargs)
  4.         self.websocket_name = self.scope['url_route']['kwargs']['websocket_name']

  5.     def websocket_connect(self, message):
  6.         print(f"连接已建立:{self.websocket_name}")
  7.         self.accept()

  8.     def websocket_receive(self, message):
  9.         self.send("不要回复不要回复")

  10.     def websocket_disconnect(self, message):
  11.         print(f"断开连接:{self.websocket_name}")
  12.         raise StopConsumer
复制代码

请注意,修改后的代码将websocket_name参数从URL中提取出来,并将其存储为ChatConsumer对象的一个属性。在websocket_connect和websocket_disconnect方法中,我们使用该属性来显示连接建立和断开的Websocket名称。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-22 14:21:22 | 显示全部楼层
在Python中,set对象有很多方法来对其进行修改,其中包括update和symmetric_difference_update方法。

update方法会将一个集合中的元素添加到当前集合中,相当于对当前集合进行并集操作。
symmetric_difference_update方法会将当前集合和另一个集合的不重复元素合并,并更新当前集合。
在你提供的代码中,使用s.symmetric_difference_update('python')和s.symmetric_difference("Python")都是将s和字符串'python'或"Python"取对称差集。但是,这两个方法的区别在于是否更新当前集合。

s.symmetric_difference_update('python')会将s和字符串'python'取对称差集,并将结果更新到s中。
s.symmetric_difference("Python")会将s和字符串'Python'取对称差集,但不会更新s,而是返回一个新的集合作为结果。
因此,使用symmetric_difference_update方法会更新s,所以最终s的值为{'o', 't', 'f', 'i', 'n', 'y', 'p', 'h', 'c', 's'}。而使用s.symmetric_difference("Python")只是返回一个新的集合,不会修改s本身,所以s的值不变,仍然为{'f', 'i', 's', 'h', 'c'}。

需要注意的是,update和symmetric_difference_update等方法都是对集合本身进行修改,不会创建新的集合。如果需要创建新的集合并保留原有集合,可以使用集合的拷贝或使用新的变量来存储结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-28 23:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表