apprtc demo的apprtc.py分析

概述

apprtc比较重要的一个文件是apprtc.py文件。
在客户端连接房间服务器时,我们可以看到除了GAE的modules.py打印信息外,apprtc.py也打印出信息。
今天我们就来搞清楚apprtc.py到底在做什么。

抓主干

在apprtc.py的最后,我们看到了这样的代码

app = webapp2.WSGIApplication([
    ('/', MainPage), 
    ('/a/', analytics_page.AnalyticsPage),
    ('/compute/(\w+)/(\S+)/(\S+)',     compute_page.ComputePage),
    ('/join/([a-zA-Z0-9-_]+)', JoinPage),
    ('/leave/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', LeavePage),
    ('/bye/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', LeavePage),
    ('/message/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', MessagePage),
    ('/params', ParamsPage),
    ('/r/([a-zA-Z0-9-_]+)', RoomPage),
], debug=True)

webapp2.WSGIApplication表明使用webapp2框架进行webapp的开发。
在网上找到GAE的webapp框架的介绍http://lampeter123.iteye.com/blog/390536
根据其中的介绍,我们可以梳理出apprtc.py的主干或者说apprtc房间服务器的主干。
一个 webapp 程序包含三个部分:
一个或多个 RequestHandler类用来处理请求和产生响应。
一个 WSGIApplication 实例用来根据发送请求的URL对应到相应的类
一个主程序用来运行 WSGIApplication(使用CGI adaptor)

app的debug=True会 打印调试信息,如果做成产品后,则可以不打印。
apprtc.py中app就是一个WSGIApplication的实例,用将请求的URL对应到对应的类。
app的对应关系为
('/', MainPage),
('/a/', analytics_page.AnalyticsPage),
('/compute/(\w+)/(\S+)/(\S+)', compute_page.ComputePage),
('/join/([a-zA-Z0-9-_]+)', JoinPage),
('/leave/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', LeavePage),
('/bye/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', LeavePage),
('/message/([a-zA-Z0-9-_]+)/([a-zA-Z0-9-_]+)', MessagePage),
('/params', ParamsPage),
('/r/([a-zA-Z0-9-_]+)', RoomPage),

具体分析

上面的代码定义了一个request handler MainPage,映射到根目录URL(/)。当房间服务器接收到客户端的一个http GET URL/的请求后,他会初始化MainPage类,然后调用这个实力的get方法。

class MainPage内容

class MainPage(webapp2.RequestHandler):
  def write_response(self, target_page, params={}):
    template = jinja_environment.get_template(target_page)
    content = template.render(params)
    self.response.out.write(content)

  def get(self):                                                     //
    """Renders index.html."""
    if self.request.headers['Host'] == 'apprtc.net':
      webapp2.redirect('https://www.apprtc.net', permanent=True)
    # Parse out parameters from request.
    params = get_room_parameters(self.request, None, None, None)
    # room_id/room_link will not be included in the returned parameters
    # so the client will show the landing page for room selection.
    self.write_response('index_template.html', params)

在GET方法中,请求信息通过self.request获得,可以看到房间服务器获得GET请求根目录的请求后,所做的是判断头中Host内容并重定向到一个域名并获取房间参数,并将index_template.html模板对应部分填充客户端输入的房间信息,然后返回给客户端。

加入房间时,提交的应该是join,其对应的处理类为JoinPage,其内容如下:

class JoinPage(webapp2.RequestHandler):
  def write_response(self, result, params, messages):
    # TODO(tkchin): Clean up response format. For simplicity put everything in
    # params for now.
    params['messages'] = messages
    self.response.write(json.dumps({
      'result': result,
      'params': params
    }))

  def write_room_parameters(self, room_id, client_id, messages, is_initiator):
    params = get_room_parameters(self.request, room_id, client_id, is_initiator)
    self.write_response('SUCCESS', params, messages)

  def post(self, room_id):
    client_id = generate_random(8)
    is_loopback = self.request.get('debug') == 'loopback'
    result = add_client_to_room(self.request, room_id, client_id, is_loopback)
    if result['error'] is not None:
      logging.info('Error adding client to room: ' + result['error'] + \
          ', room_state=' + result['room_state'])
      self.write_response(result['error'], {}, [])
      return

    self.write_room_parameters(
        room_id, client_id, result['messages'], result['is_initiator'])
    logging.info('User ' + client_id + ' joined room ' + room_id)
    logging.info('Room ' + room_id + ' has state ' + result['room_state'])

提交Http 的Post请求到join/roomID时,初始化JoinPage类并且用post函数来处理。

//计算一个clietn_id值
client_id = generate_random(8)
//判断是否是本地测试;
is_loopback = self.request.get('debug') == 'loopback'
//添加客户端到房间的结果
result = add_client_to_room(self.request, room_id, client_id, is_loopback)
if result['error'] is not None:
//错误信息输出并退出
      logging.info('Error adding client to room: ' + result['error'] + \
          ', room_state=' + result['room_state'])
      self.write_response(result['error'], {}, [])
      return
//获取房间参数并返回房间参数信息给客户端,包括client_ID
    self.write_room_parameters(
        room_id, client_id, result['messages'], result['is_initiator'])
//打印日志信息
    logging.info('User ' + client_id + ' joined room ' + room_id)
    logging.info('Room ' + room_id + ' has state ' + result['room_state'])
  def write_room_parameters(self, room_id, client_id, messages, is_initiator):
    params = get_room_parameters(self.request, room_id, client_id, is_initiator)
    self.write_response('SUCCESS', params, messages)
 def write_response(self, result, params, messages):
    # TODO(tkchin): Clean up response format. For simplicity put everything in
    # params for now.
    params['messages'] = messages
    self.response.write(json.dumps({
      'result': result,
      'params': params
    }))

进入房间后,应该提交http Get 到/r/roomId信息到房间服务器,此时初始化class roompage。其内容为

class RoomPage(webapp2.RequestHandler):                           //回调函数
  def write_response(self, target_page, params={}):
    template = jinja_environment.get_template(target_page)
    content = template.render(params)
    self.response.out.write(content)

  def get(self, room_id):
    """Renders index.html or full.html."""
    # Check if room is full.
    room = memcache.get(
        get_memcache_key_for_room(self.request.host_url, room_id))
    if room is not None:
      logging.info('Room ' + room_id + ' has state ' + str(room))
      if room.get_occupancy() >= 2:
        logging.info('Room ' + room_id + ' is full')
        self.write_response('full_template.html')
        return
    # Parse out room parameters from request.
    params = get_room_parameters(self.request, room_id, None, None)
    # room_id/room_link will be included in the returned parameters
    # so the client will launch the requested room.
    self.write_response('index_template.html', params)

会使用get函数进行处理,基本应该就是根据房间状态, 返回状态,如果放假非空,则输出房间状态, 并且如果房间超过2个客户端,则输出full_template.html模板。也就是建立房间后,如果房间数大于2个,则会提示房间满的页面。可以通过这个来调节输出房间满的条件。
其他分析类似

其中compute_page.ComputePage表示的是compute_page.py中的ComputePage类。

基本分析就是如此。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章