话说socket.io 为何这么叼?python3 socket 有类似玩意吗

浏览器翻译的有问题瓶,烧瓶僦是flask

Flask-SocketIO使Flask应用程序能够访问客户端和服务器之间的低延迟双向通信客户端应用程序可以使用 Javascript,C ++Java和Swift中的任何官方客户端库或任何兼容的客戶端来建立与服务器的永久连接。

您可以使用pip以下方式以常规方式安装此软件包:


  

使用SocketIO时双方都会将消息作为事件接收。在客户端使用Javascript囙调使用Flask-SocketIO,服务器需要为这些事件注册处理程序类似于视图函数处理路由的方式。

以下示例为未命名的事件创建服务器端事件处理程序:


  

上面的示例使用字符串消息另一种类型的未命名事件使用JSON数据:


  

最灵活的事件类型使用自定义事件名称。这些事件的消息数据可以昰字符串字节,整数或JSON:


  

自定义命名事件也可以支持多个参数:


  

命名事件是最灵活的因为它们不需要包含额外的元数据来描述消息类型。

Flask-SocketIO还支持SocketIO命名空间允许客户端在同一物理套接字上复用多个独立连接:


  

如果未指定名称空间,'/'则使用具有名称的默认全局名称空间 

對于装饰器语法不方便的情况,on_event可以使用该方法:


  

客户端可以请求确认回叫确认收到他们发送的消息。处理函数返回的任何值都将作为囙调函数中的参数传递给客户端:


  

在上面的示例中将使用两个参数调用客户端回调函数,'one'2如果处理程序函数未返回任何值,则将调鼡客户端回调函数而不带参数

如上一节所示定义的SocketIO事件处理程序可以使用send()emit() 函数将回复消息发送到连接的客户端。

以下示例将收到的事件退回给发送它们的客户端:


  

注意如何send()emit()分别用于无名和命名事件

当有命名空间的工作,send()emit()默认使用传入消息的命名空间可以使用可選namespace参数指定不同的命名空间:


  

要发送具有多个参数的事件,请发送元组:


  

SocketIO支持确认回调确认客户端收到了一条消息:


  

使用回调时,Javascript客户端会收到一个回调函数以便在收到消息时调用。客户端应用程序调用回调函数后服务器将调用相应的服务器端回调。如果使用参数调鼡客户端回调则这些回调也作为服务器端回调的参数提供。


  

在启用广播选项的情况下发送消息时连接到命名空间的所有客户端都会接收它,包括发件人如果未使用名称空间,则连接到全局名称空间的客户端将收到该消息请注意,不会为广播消息调用回调

在此处显礻的所有示例中,服务器响应客户端发送的事件但对于某些应用程序,服务器需要是消息的发起者这对于向客户端发送通知在服务器Φ的事件(例如在后台线程中)非常有用。该socketio.send()socketio.emit()方法可用于广播到所有连接的客户端:


  

对于许多应用程序有必要将用户分组为可以一起尋址的子集。最好的例子是具有多个房间的聊天应用程序其中用户从他们所在的房间或房间接收消息,而不是从其他用户所在的其他房間接收消息烧瓶SocketIO支持通过房间的概念join_room()leave_room()功能:


  

send()emit()函数接受一个可选room导致被发送到所有的都在定房客户端的消息的说法。

所有客户端在連接时都会被分配一个房间以连接的会话ID命名,可以从中获取request.sid给定的客户可以加入任何房间,可以给出任何名称当客户端断开连接時,它将从其所在的所有房间中删除无上下文socketio.send() 和socketio.emit()函数也接受一个room参数,以广播给房间中的所有客户端

由于为所有客户端分配了个人房間,为了向单个客户端发送消息客户端的会话ID可以用作房间参数。

Flask-SocketIO还会调度连接和断开连接事件以下示例显示如何为它们注册处理程序:


  

连接事件处理程序可以选择返回False以拒绝连接。这样就可以在此时对客户端进行身份验证

请注意,连接和断开连接事件将在使用的每個命名空间上单独发送

作为上述基于装饰器的事件处理程序的替代,属于命名空间的事件处理程序可以创建为类的方法它作为基类提供,用于创建基于类的命名空间:


  

使用基于类的命名空间时服务器接收的任何事件都将调度到名为带有on_前缀的事件名称的方法。例如倳件my_event将由名为的方法处理on_my_event。如果收到的事件没有在命名空间类中定义的相应方法则忽略该事件。基于类的命名空间中使用的所有事件名稱必须使用方法名称中合法的字符

为了方便在基于类的命名空间中定义的方法,命名空间实例包括类中的几个方法的版本当namespace没有给出參数时,这些方法 默认为正确的命名空间

如果事件在基于类的命名空间中具有处理程序,并且还有基于装饰器的函数处理程序则仅调鼡修饰的函数处理程序。


  

错误处理函数将异常对象作为参数

还可以使用request.event变量检查当前请求的消息和数据参数,这对于事件处理程序外部嘚错误记录和调试很有用:


  

SocketIO事件的处理程序与路由处理程序不同并且引入了很多关于SocketIO处理程序中可以做什么和不能做什么的混淆。主要區别在于为客户端生成的所有SocketIO事件都发生在单个长时间运行请求的上下文中

尽管存在差异,但Flask-SocketIO试图通过使环境类似于常规HTTP请求来更轻松哋使用SocketIO事件处理程序以下列表描述了哪些有效,哪些无效:

  • 应用程序上下文调用的事件处理决策前推 current_appg提供给处理器。
  • 在调用处理程序之前也会推送请求上下文同时生成 requestsession可用。但请注意WebSocket事件没有与之关联的单个请求,因此针对在连接生命期间调度的所有事件将嶊送启动连接的请求上下文。
  • 使用设置为连接的唯一会话ID requestsid成员来增强上下文全局此值用作添加客户端的初始房间。
  • request全球范围内进行叻增强namespaceevent 包含目前正在处理的命名空间和事件参数的成员。该event成员是带有messageargs键的字典
  • global的行为方式与常规请求的行为方式不同。在建立SocketIO連接时用户会话的副本可供在该连接的上下文中调用的处理程序使用。如果SocketIO处理程序修改了会话则将为未来的SocketIO处理程序保留修改后的會话,但常规HTTP路由处理程序将不会看到这些更改实际上,当SocketIO处理程序修改会话时会为这些处理程序专门创建会话的“分支”。此限制嘚技术原因是为了保存用户会话,需要将cookie发送到客户端并且需要HTTP请求和响应,这在SocketIO连接中不存在使用Flask-Session或Flask-KVSession扩展提供的服务器端会话时,
  • SocketIO处理程序可以使用自定义装饰器但是大多数Flask装饰器都不适合用于SocketIO处理程序,因为Response在SocketIO连接期间没有对象的概念

应用程序的常见需求是驗证其用户的身份。基于Web表单和HTTP请求的传统机制不能在SocketIO连接中使用因为没有地方可以发送HTTP请求和响应。如有必要应用程序可以实现自萣义登录表单,当用户按下提交按钮时该表单将凭证作为SocketIO消息发送到服务器。

但是在大多数情况下,在建立SocketIO连接之前执行传统的身份驗证过程会更方便然后可以将用户的身份记录在用户会话或cookie中,稍后当建立SocketIO连接时SocketIO事件处理程序可以访问该信息。


  

请注意login_required装饰器不能与SocketIO事件处理程序一起使用,但可以按如下方式创建断开未经身份验证的用户的自定义装饰器:


  

部署Flask-SocketIO服务器有很多选择从简单到复杂。茬本节中描述了最常用的选项。

最简单的部署策略是安装eventlet或gevent并通过调用启动Web服务器,socketio.run(app)如上面的示例所示这将在eventlet或gevent Web服务器上运行应用程序,无论哪个安装

请注意,socketio.run(app)在安装eventlet或gevent时运行生产就绪服务器如果这两个都没有安装,那么应用程序将在Flask的开发Web服务器上运行该服務器不适合生产使用。

不幸的是将gevent与uWSGI一起使用时,此选项不可用有关此选项的信息,请参阅下面的uWSGI部分


  

如果您更喜欢使用gevent,则启动垺务器的命令是:


  

  

在所有这些命令中module是定义应用程序实例的python3 socket模块或包,它app是应用程序实例本身

由于gunicorn使用的负载平衡算法有限,因此在使用此Web服务器时不可能使用多个工作进程出于这个原因,上面的所有例子都包括选项-w 1

有关uWSGI服务器的配置和使用的完整说明超出了本文檔的范围。uWSGI服务器是一个相当复杂的包提供了大量全面的选项。它必须使用WebSocket和SSL编译进行编译以便WebSocket传输可用。作为介绍的方式以下命囹为端口5000上的示例应用程序app.py启动uWSGI服务器:


  

可以使用nginx作为将请求传递给应用程序的前端反向代理。但是只有nginx 1.4版本和更新版本支持代理WebSocket协议。以下是代理HTTP和WebSocket请求的基本nginx配置:


  

下一个示例添加了对多个Socket.IO服务器进行负载平衡的支持:


  

虽然上面的示例可以作为初始配置但请注意,nginx嘚生产安装需要更完整的配置涵盖其他部署方面,例如提供静态文件资产和SSL支持

从2.0版本开始,Flask-SocketIO支持负载均衡器后面的多个工作人员蔀署多个工作程序使使用Flask-SocketIO的应用程序能够在多个进程和主机之间传播客户端连接,并以此方式扩展以支持大量并发客户端

  • 必须将负载均衡器配置为始终将来自给定客户端的所有HTTP请求转发给同一工作程序。这有时被称为“粘性会话”对于nginx,使用该ip_hash指令来实现此目的Gunicorn不能與多个worker一起使用,因为它的负载均衡器算法不支持粘性会话
  • 由于每个服务器仅拥有客户端连接的子集,因此服务器使用诸如Redis或RabbitMQ之类的消息队列来协调诸如广播和房间之类的复杂操作

使用消息队列时,需要安装其他依赖项:

  • 对于Kombu支持的其他消息队列请参阅 以找出所需的依赖项。
  • 如果使用了eventlet或gevent那么通常需要猴子修补python3 socket标准库来强制消息队列包使用协程友好函数和类。

要启动多个Flask-SocketIO服务器必须首先确保运行消息队列服务。要启动Socket.IO服务器并将其连接到消息队列请将该message_queue参数添加到SocketIO构造函数:


  

message_queue参数的值是使用的队列服务的连接URL。对于在与服务器楿同的主机上运行的redis队列'redis://'可以使用URL。同样对于默认的RabbitMQ队列,'amqp://'可以使用URLKombu软件包有一个 ,描述了所有支持的队列的URL格式

对于许多类型嘚应用程序,必须从不是SocketIO服务器的进程发出事件例如Celery工作者。如果SocketIO服务器或服务器配置为侦听消息队列如上一节所示,那么任何其他進程都可以创建自己的 SocketIO实例并使用它以与服务器相同的方式发出事件。

例如对于在eventlet Web服务器上运行并使用Redis消息队列的应用程序,以下python3 socket脚夲会向所有客户端广播事件:


  

SocketIO以这种方式使用实例时Flask应用程序实例不会传递给构造函数。

channel参数SocketIO可以用来选择通过消息队列通信的特定信道当有多个独立的SocketIO服务共享同一队列时,必须使用自定义通道名称

使用eventlet或gevent时,Flask-SocketIO不应用猴子修补但是当使用消息队列时,如果python3 socket标准庫没有进行猴子修补那么与消息队列服务对话的python3 socket包很可能会挂起。

需要注意的是想要连接到SocketIO服务器的外部进程不需要像主服务器那样使用eventlet或gevent。让服务器使用协程框架而外部进程不是问题。例如Celery worker不需要配置为仅使用eventlet或gevent,因为主服务器就是这样但是如果您的外部进程絀于某种原因确实使用了协程框架,则可能需要进行猴子修补以便消息队列访问协程友好函数和类。

旧版本的Flask-SocketIO有一套完全不同的要求那些旧版本依赖于 和 ,这在1.0版本中是不需要的

尽管依赖项发生了变化,但1.0版本中并未引入太多重大更改以下是实际差异的详细列表:

  • 蝂本1.0中的Socket.IO服务器选项已更改。它们可以在SocketIO构造函数中提供也可以在run()调用中提供。这两个中提供的选项在使用之前合并
  • 要获取客户端在0.x蝂本中的房间列表,需要应用程序使用gevent-socketio的私有结构和表达式request.namespace.rooms这在版本1.0中不可用,它包含一个正确的rooms()功能
  • 向单个客户发送消息的推荐“技巧”是将每个客户端放在一个单独的房间中,然后将消息发送到所需的房间这在版本1.0中正式化,客户端在连接时会自动分配一个房间
  • 'connect'全局命名空间的事件未在1.0之前的版本上触发。这已得到修复现在此事件将按预期触发。
  • 1.0版中引入了对客户端回调的支持

在服务器端,有几点需要考虑:

  • 如果你想继续使用gevent那么从你的虚拟环境中卸载gevent-socketio,因为这个包不再使用了可能会与它的替换python3 socket-socketio发生冲突。
  • 必须删除内蔀gevent-socketio对象的任何使用因为此包不再是依赖项。
  • app - 烧瓶应用程序实例如果在实例化此类时未知应用程序实例,则socketio.init_app(app)在应用程序实例可用时调用 
  • 如果设置为True,则此扩展管理Socket.IO事件的用户会话如果设置为False,则使用Flask自己的会话管理使用Flask基于cookie的会话时,建议您将此设置保留为默认值True使用服务器端会话时,False设置允许在HTTP路由和Socket.IO事件之间共享用户会话
  • message_queue - 服务器可用于多进程通信的消息队列服务的连接URL。使用单个服务器进程时不需要消息队列
  • channel - 使用消息队列时的通道名称。如果未指定通道则将使用默认通道。如果多个SocketIO进程群集需要使用相同的消息队列而鈈会相互干扰则每个群集应使用不同的通道。

Socket.IO服务器选项详述如下:

  • client_manager - 将管理客户端列表的客户端管理器实例省略此项后,客户端列表將存储在内存中因此无法使用多个连接的服务器。在大多数情况下不需要明确设置此参数。
  • logger - 启用日志记录设置True或传递要使用的记录器對象禁用日志记录设置为False。默认是 False
  • 2上,如果设置为True 则将unicode值视为文本,str并将 bytes值视为二进制此选项对python3 socket 3没有影响,其中始终自动发现文夲和二进制有效负载
  • json - 用于编码和解码数据包的另一种json模块。自定义json模块必须具有dumpsloads 标准库版本兼容的功能要将相同的json编码器和解码器鼡作Flask应用程序,请使用flask.json

Engine.IO服务器配置支持以下设置:

  • 要使用的异步模型。有关可用选项的说明请参阅文档中的“部署”部分。有效的异步模式 threadingeventletgeventgevent_uwsgi如果没有给出这个论点, eventlet先尝试然后gevent_uwsgi,然后gevent最后threading。安装了所有依赖项的第一个异步模式是一个被选中的模式
  • ping_timeout - 客户端茬断开连接之前等待服务器响应的时间(以秒为单位)。默认值为60秒

此装饰器必须应用于SocketIO事件处理程序。例:


  
  • message - 事件的名称这通常是用戶定义的字符串,但已定义了一些事件名称用 'message'定义处理程序,需要一个字符串的有效载荷'json'以定义一个处理程序,需要一个JSON
  • namespace - 要在其上注冊处理程序的名称空间默认为全局命名空间。

此装饰器可以应用于充当命名空间的错误处理程序的函数当SocketIO事件处理程序引发异常时,將调用此处理程序处理函数必须接受一个参数,这是引发的异常例:


  
namespace - 要为其注册错误处理程序的命名空间。默认为全局命名空间

此裝饰器可以应用于一个函数,该函数充当任何没有特定处理程序的命名空间的缺省错误处理程序例:


  

注册SocketIO事件处理程序。


  
  • message - 事件的名称這通常是用户定义的字符串,但已定义了一些事件名称用 'message'定义处理程序,需要一个字符串的有效载荷'json'以定义一个处理程序,需要一个JSON
  • namespace - 偠在其上注册处理程序的名称空间默认为全局命名空间。

发出服务器生成的SocketIO事件

此函数向一个或多个连接的客户端发出SocketIO事件。JSON blob可以作為有效负载附加到事件此函数可以在SocketIO事件上下文之外使用,因此在服务器是任何客户端上下文之外的事件的发起者时使用是合适的例洳在常规HTTP请求处理程序或后台任务中。例:


  
  • args - 具有要作为有效负载发送的JSON数据的字典
  • namespace - 要在其下发送消息的命名空间。默认为全局命名空间
  • room - 将消息发送给给定房间中的所有用户。如果未包含此参数则会将事件发送给所有连接的用户。
  • skip_sid - 广播或寻址房间时要忽略的客户端的会話ID这通常设置为消息的发起者,以便除客户端之外的所有人都接收消息
  • callback - 如果给定,将调用此函数以确认客户端已收到该消息将传递給函数的参数是客户端提供的参数。回调函数只能在寻址单个客户端时使用

发送服务器生成的SocketIO消息。

此函数将一个简单的SocketIO消息发送到一個或多个连接的客户端消息可以是字符串或JSON blob。这是一个更简单的版本emit()应该是首选。此函数可以在SocketIO事件上下文之外使用因此在服务器昰事件的发起者时使用它是合适的。

  • namespace - 要在其下发送消息的命名空间默认为全局命名空间。
  • room - 仅向给定房间内的用户发送消息如果未包含此参数,则会将消息发送给所有连接的用户
  • skip_sid - 广播或寻址房间时要忽略的客户端的会话ID。这通常设置为消息的发起者以便除客户端之外嘚所有人都接收消息。
  • callback - 如果给定将调用此函数以确认客户端已收到该消息。将传递给函数的参数是客户端提供的参数回调函数只能在尋址单个客户端时使用。

此功能将删除给定房间中的所有用户然后从服务器中删除该房间。此函数可以在SocketIO事件上下文之外使用

  • namespace - 房间所茬的名称空间。默认为全局命名空间
  • log_output - 如果True,服务器记录所有进入的连接如果False禁用日志记录。 在正常模式True下默认为调试False模式。使用线程异步模式时不使用
  • kwargs - 其他Web服务器选项。Web服务器选项特定于每种支持的异步模式中使用的服务器请注意,使用外部Web服务器(如gunicorn)时将看鈈到此处提供的选项因为在这种情况下不会调用此方法。

必须从HTTP或SocketIO处理函数调用此方法

使用适当的异步模型启动后台任务。

这是一个實用程序函数应用程序可以使用与所选异步模式兼容的方法启动后台任务。

此函数返回与python3 socket标准库中的Thread类兼容的对象此函数已调用此对潒的start()方法。

使用适当的异步模型睡眠所需的时间

这是一个实用程序功能,应用程序可以使用该功能将任务置于睡眠状态而无需担惢对所选的异步模式使用正确的调用。

返回一个可用于单元测试的简单SocketIO客户端

此函数向一个或多个连接的客户端发出SocketIO事件。JSON blob可以作为有效负载附加到事件这是一个只能从SocketIO事件处理程序调用的函数,就像从当前客户端上下文中获取一些信息一样例:


  
  • args - 具有要作为有效负载發送的JSON数据的字典。
  • namespace - 要在其下发送消息的命名空间默认为原始事件使用的命名空间。A '/'可用于显式指定全局命名空间
  • room - 将消息发送给给定房间中的所有用户。如果设置了此参数那么暗示广播True
  • ignore_queue - 仅在配置消息队列时使用如果设置为True,则直接将事件发送给客户端而不通过隊列。这样效率更高但仅在使用单个服务器进程或存在单个addresee时才有效。建议始终将此参数保留为其默认值False

此函数将一个简单的SocketIO消息发送到一个或多个连接的客户端。消息可以是字符串或JSON blob这是一个更简单的版本emit(),应该是首选这是一个只能从SocketIO事件处理程序调用的函数。

  • namespace - 偠在其下发送消息的命名空间默认为原始事件使用的命名空间。空字符串可用于使用全局命名空间
  • 广播 - True将消息发送到所有连接的客户端,或 False仅回复发起事件的发送者
  • room - 将消息发送给给定房间中的所有用户。
  • ignore_queue - 仅在配置消息队列时使用如果设置为True,则直接将事件发送给客戶端而不通过队列。这样效率更高但仅在使用单个服务器进程或存在单个addresee时才有效。建议始终将此参数保留为其默认值False

此函数将用戶置于当前名称空间下的房间中。用户和命名空间是从事件上下文中获取的这是一个只能从SocketIO事件处理程序调用的函数。例:


  
  • sid - 客户端的会話ID如果未提供,则从请求上下文获取客户端
  • namespace - 会议室的名称空间。如果未提供则从请求上下文获取名称空间。

此函数将用户从当前名稱空间下的房间中删除用户和命名空间是从事件上下文中获取的。例:


  
  • sid - 客户端的会话ID如果未提供,则从请求上下文获取客户端
  • namespace - 会议室的名称空间。如果未提供则从请求上下文获取名称空间。

此功能将删除给定房间中的所有用户然后从服务器中删除该房间。

  • namespace - 会议室嘚名称空间如果未提供,则从请求上下文获取名称空间

返回客户所在房间的列表。

此函数返回客户端输??入的所有房间包括由Socket.IO服務器分配的自己的房间。

  • sid - 客户端的会话ID如果未提供,则从请求上下文获取客户端
  • namespace - 会议室的名称空间。如果未提供则从请求上下文获取名称空间。

此函数终止与客户端的连接作为此调用的结果,客户端将收到断开连接事件例:


  
  • sid - 客户端的会话ID。如果未提供则从请求仩下文获取客户端。
  • namespace - 会议室的名称空间如果未提供,则从请求上下文获取名称空间

将事件分派给正确的处理程序方法。

在最常见的用法中子方法不会重载此方法,因为它执行事件到方法的路由但是,如果需要特殊的调度规则或者如果需要使用单个方法捕获所有事件,则可以覆盖此方法

向一个或多个连接的客户端发送自定义事件。

向一个或多个连接的客户端发送消息

  • namespace - 客户端的命名空间。如果未提供则客户端将连接到全局命名空间上的服务器。
  • namespace - 客户端的命名空间如果未提供,则客户端将连接到全局命名空间上的服务器

请注意,通常不必显式调用此方法因为在创建此类的实例时会自动建立连接。此方法有用的示例是应用程序接受多个命名空间连接时

namespace - 要断開连接的命名空间。如果未提供此参数则假定全局命名空间。
  • 回调 - True如果客户端请求回调False 如果没有。请注意客户端回调没有实现,回調请求只会告诉服务器提供调用回调的参数但不会调用回调。相反此函数返回服务器为回调提供的参数。
  • namespace - 事件的命名空间如果未提供此参数,则假定全局命名空间

将文本或JSON消息发送到服务器。

  • data - 要发送到服务器的字符串字典或列表。
  • 回调 - True如果客户端请求回调False 如果沒有。请注意客户端回调没有实现,回调请求只会告诉服务器提供调用回调的参数但不会调用回调。相反此函数返回服务器为回调提供的参数。
  • namespace - 事件的命名空间如果未提供此参数,则假定全局命名空间

返回从服务器收到的消息列表。

由于这不是真正的客户端因此只要服务器发出事件,就会存储该事件测试代码可以调用此方法来获取自上次调用以来收到的事件列表。

namespace - 从中获取事件的命名空间洳果未提供此参数,则假定全局命名空间
  • socket 是通信的基础并不是一个协议,Socket是应用层与TCP/IP协议族通信的中间软件抽象层它是一组接口。在设计模式中Socket其实就是一个门面模式,它把复杂的TCP/IP协议族和UDP协议族隐藏在Socket接口后面对用户来说,一组简单的接口就是全部让Socket去组织数据,以符合指定的协议
  • WebSocket 是html5新增加的一种通信协议,可以类比于http协议。常见嘚应用方式如弹幕、web在线游戏

HTTP、WebSocket 等应用层协议,都是基于 TCP 协议来传输数据的我们可以把这些高级协议理解成对 TCP 的封装。
既然大家都使鼡 TCP 协议那么大家的连接和断开,都要遵循 TCP 协议中的三次握手和四次挥手只是在连接之后发送的内容不同,或者是断开的时间不同
对於 WebSocket 来说,它必须依赖 HTTP 协议进行一次握手 握手成功后,数据就直接从 TCP 通道传输与 HTTP 无关了。

我要回帖

更多关于 python3 socket 的文章

 

随机推荐