资讯专栏INFORMATION COLUMN

实践,用tornado实现自定义协议server

wizChen / 1646人阅读

摘要:前言俗话说光说不练假把式上一篇文里都只是光看着别人的源码说貌似有点纸上谈兵的意思所以这次写一个简单的自己定义协议的既可以熟悉和的用法又可以在去除了复杂的协议后了解的工作原理代码不多加上空行和也就行不到在上的源码点这里目标定义一个简单的协议达

前言

俗话说"光说不练假把式",上一篇文里都只是光看着别人的源码说,貌似有点纸上谈兵的意思.
所以这次写一个简单的,自己定义协议的server.
既可以熟悉Future和coroutine的用法,又可以在去除了复杂的http协议后,了解tornado的工作原理.
代码不多,加上空行和import也就200行不到.
在github上的源码点这里

目标

1.定义一个简单的协议,达到远程调用的效果,并且是个长连接的协议(类似websock)

2.模仿tornado的框架模式开发这个server框架,让用户代码开发方便,并且支持coroutine

3.为了省去客户端的开发,客户端使用telnet

协议

1.客户端连接成后,以换行符分割每次通信内容

2.第一次通信内容是需要执行handler名称,第二次通信的内容是该handler的方法名

3.对于客户端的主动close,需等待此连接所有的异步操作完成后才关闭连接
最后运行方式如下图:

源码说明 总览

因为想让代码尽量少,所以委托模式没有严格按照设计模式的规范写,直接忽略掉了interface的定义.严格来说是需要定义interface和判断传入参数的类型的(泛华)
这是类的实例关系图(也不知道是不是这样画...)

MyServer和MyApplication的实例常驻.一个连接进来后就会创建图中其他的实例各一个.

异步说明

1.为了达到目标中的第一点,需要一个while循环,读取了客户端数据后,执行handler,
立即继续读取下一条客户端数据.直到客户端关闭操作,引发StreamClosedError才退出循环

2.为了达到目标中的第二点,判断handler的返回值,如果类型是Future则yield处理,因为本方法有@gen.coroutine,所以yield就代表异步操作是在gen.Runner中执行的.

3.为了达到目标中的第三点,需要记录每一个异步操作,并且异步操作完成后移除.当客户端主动关闭连接时,需判断是否还有future未完成.所以close代码中给每个future加上done_callback,用以检查关闭

详情见代码 MyServerConnection._server_request_loop

@gen.coroutine
    def _server_request_loop(self, delegate):
        try:
            #get request adepter
            request_delegate = delegate.on_request(self)
            while True:

                try:
                    message_future = self.stream.read_until_regex(b"

?")
                    message = yield message_future
                    message = self._parse_data(message)

                except (iostream.StreamClosedError, 
                        iostream.UnsatisfiableReadError):
                    app_log.error(" close the connect")
                    self.close()
                    return

                except Exception:

                    gen_log.error("Uncaught exception", exc_info=True)
                    self.close()
                    return

                ret = request_delegate.on_message(message)
                #如果是异步执行的方法,保存future,用于确保close时,所有future都已完成
                if isinstance(ret, Future):
                    ret.add_done_callback(lambda f:self._serving_futures.remove(f))
                    self._serving_futures.append(ret)

        finally:
            delegate.on_close(self)
    def close(self):

        def mayby_close(f):
            futures = self._serving_futures+self._pending_writes
            app_log.error(futures)
            if not any(futures):
                self.stream.close()

        pending_futrues = self._serving_futures+self._pending_writes
        if any(pending_futrues):
            map(lambda f:f.add_done_callback(mayby_close),pending_futrues)
        else:
            self.stream.close()
关于@coroutine

其实用@coroutine的时候只需要记住几点就行了
* 1.被包装的函数(方法),返回值是Future,
* 2.被包装的函数走完最后一行代码后,返回的Futurecallback就会被运行(因为在Runner中引发了StopIteration错误,被set_result了)
* 3.被包装的函数是在gen.Runner中运行的,而Runner是在ioloop(callback那块)中运行的

总结

代码非常简单,因为tornado为我们提供了异步的库(tornado真强大,协程好厉害!!),并且是单进程的编程,不需要考虑锁,写起来就更轻松了.
最后附上程序效果图

废话

这只是个吃饱撑着的程序,一点实际作用都没啊(好想被拍死!).吃饱撑着的原因是我还没下决心去找工作...工作太难找啦(哭~~)!!!!好想被带走.................

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37587.html

相关文章

  • [零基础学python]Hello,第一个网页分析

    摘要:的非阻塞单线程的特点在这个模块中体现。还有一个模块引入,是用完成的这两句就显示了所谓命令行解析模块的用途了。表示可以接收来自的请求了。以上把一个简单的剖析。 As he walked by the sea of Galilee, he saw two brothers, Simon, who is called Peter, and Andrew his brother, cas...

    Steve_Wang_ 评论0 收藏0
  • tornado配合celery及rabbitmq实现web request异步非阻塞

    摘要:主要是为了实现系统之间的双向解耦而实现的。问题及优化队列过长问题使用上述方案的异步非阻塞可能会依赖于的任务队列长度,若队列中的任务过多,则可能导致长时间等待,降低效率。 Tornado和Celery介绍 1.Tornado Tornado是一个用python编写的一个强大的、可扩展的异步HTTP服务器,同时也是一个web开发框架。tornado是一个非阻塞式web服务器,其速度相当快。...

    番茄西红柿 评论0 收藏0
  • 己写一个 wsgi 服务器运行 Django 、Tornado 等框架应

    摘要:要使用协议我们不可能自己实现一个,现在比较流行的解决方案就是使用套接字编程,已经帮我们实现了协议的细节,我们可以直接拿来使用不用关心细节。 前几天写了 浅谈cgi、wsgi、uwsgi 与 uWSGI 等一些 python web 开发中遇到的一些名词的理解,今天博主就根据 wsgi 标准实现一个 web server,并尝试用它来跑 Django、tornado 框架的 app。 编...

    lunaticf 评论0 收藏0
  • Tornado 4.3文档翻译: web框架-RequestHandler和Application

    摘要:译者说于年月日发布,该版本正式支持的关键字,并且用旧版本编译同样可以使用这两个关键字,这无疑是一种进步。其次,这是最后一个支持和的版本了,在后续的版本了会移除对它们的兼容。本节最好直接在或者阅读,以获得更好的阅读体验格式支持。 译者说 Tornado 4.3于2015年11月6日发布,该版本正式支持Python3.5的async/await关键字,并且用旧版本CPython编译Torn...

    xiongzenghui 评论0 收藏0
  • Tornado 4.3文档翻译: web框架-RequestHandler和Application

    摘要:译者说于年月日发布,该版本正式支持的关键字,并且用旧版本编译同样可以使用这两个关键字,这无疑是一种进步。其次,这是最后一个支持和的版本了,在后续的版本了会移除对它们的兼容。本节最好直接在或者阅读,以获得更好的阅读体验格式支持。 译者说 Tornado 4.3于2015年11月6日发布,该版本正式支持Python3.5的async/await关键字,并且用旧版本CPython编译Torn...

    mykurisu 评论0 收藏0

发表评论

0条评论

wizChen

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<