既然你也看过相关代码了,那么我把源码放出来交流下
首先是join_room()
函数:
def join_room(room, sid=None, namespace=None):
"""Join a room.
This function puts the user in a room, under the current namespace. The
user and the namespace are obtained from the event context. This is a
function that can only be called from a SocketIO event handler. Example::
@socketio.on('join')
def on_join(data):
username = session['username']
room = data['room']
join_room(room)
send(username + ' has entered the room.', room=room)
:param room: The name of the room to join.
:param sid: The session id of the client. If not provided, the client is
obtained from the request context.
:param namespace: The namespace for the room. If not provided, the
namespace is obtained from the request context.
"""
socketio = flask.current_app.extensions['socketio']
sid = sid or flask.request.sid
namespace = namespace or flask.request.namespace
socketio.server.enter_room(sid, room, namespace=namespace)
函数明显还有一个关键字参数sid
,如果没有提供则从flask.request.sid
获取。实际上如果打开浏览器控制台(浏览器按F12),查看socketio的连接,可以发现在query string里都会带有sid
参数。
继续往下看,join_room()
把几个参数赋给了socketio.server
的enter_room()
方法。
import socketio
...
class SocketIO(object):
def __init__(self, app=None, **kwargs):
...
if app is not None or 'message_queue' in kwargs:
self.init_app(app, **kwargs)
def init_app(self, app, **kwargs):
...
self.server = socketio.Server(**self.server_options)
...
def join_room(room, sid=None, namespace=None):
...
socketio.server.enter_room(sid, room, namespace=namespace)
下面开始进入socketio
(python_socketio
)的源码
class Server(object):
def __init__(self, client_manager=None, logger=False, binary=False,
json=None, async_handlers=True, always_connect=False,
**kwargs):
...
if client_manager is None:
client_manager = base_manager.BaseManager()
self.manager = client_manager
...
...
def enter_room(self, sid, room, namespace=None):
namespace = namespace or '/'
self.logger.info('%s is entering room %s [%s]', sid, room, namespace)
self.manager.enter_room(sid, namespace, room)
继续追踪base_manager.BaseManager()
,找enter_room()
方法的实现:
class BaseManager(object):
def __init__(self):
...
self.rooms = {}
def enter_room(self, sid, namespace, room):
"""Add a client to a room."""
if namespace not in self.rooms:
self.rooms[namespace] = {}
if room not in self.rooms[namespace]:
self.rooms[namespace][room] = {}
self.rooms[namespace][room][sid] = True # 把sid加入该namespace的room
def leave_room(self, sid, namespace, room):
"""Remove a client from a room."""
try:
del self.rooms[namespace][room][sid] # 从namespace的room移除sid
if len(self.rooms[namespace][room]) == 0:
del self.rooms[namespace][room]
if len(self.rooms[namespace]) == 0:
del self.rooms[namespace]
except KeyError:
pass
自此就可以看到一个room就是把sid
存到相关字典里。