在这个demo中,主要是使用了Tornado中异步的TCP client和server来实现一个简单的echo效果(即客户端发送的message会从server端返回到client)。代码的github链接点这里

1 Server端代码分析

  1. import logging
  2. from tornado.ioloop import IOLoop
  3. from tornado import gen
  4. from tornado.iostream import StreamClosedError
  5. from tornado.tcpserver import TCPServer
  6. from tornado.options import options, define
  7.  
  8. define("port", default=9888, help="TCP port to listen on")
  9. logger = logging.getLogger(__name__)
  10.  
  11. class EchoServer(TCPServer):
  12. @gen.coroutine
  13. def handle_stream(self, stream, address):
  14. while True:
  15. try:
  16. data = yield stream.read_until(b"\n")
  17. logger.info("Received bytes: %s", data)
  18. if not data.endswith(b"\n"):
  19. data = data + b"\n"
  20. yield stream.write(data)
  21. except StreamClosedError:
  22. logger.warning("Lost client at host %s", address[0])
  23. break
  24. except Exception as e:
  25. print(e)
  26.  
  27. if __name__ == "__main__":
  28. options.parse_command_line()
  29. server = EchoServer()
  30. server.listen(options.port)
  31. logger.info("Listening on TCP port %d", options.port)
  32. IOLoop.current().start()

server.py

涉及到引入的模块及作用:

  1. import logging //用来记录日志
    from tornado.ioloop import IOLoop
    from tornado import gen //实现异步
    from tornado.iostream import StreamClosedError //处理iostream
    from tornado.tcpserver import TCPServer // 非阻塞单线程的TCP server及其相关哦功能
    from tornado.options import options, define // options参数相关

server端代码并不复杂,首先定义了默认的监听端口,并且生成了一个logger实例。(logging用法点这里。)

  1. define("port", default=9888, help="TCP port to listen on")
  2. logger = logging.getLogger(__name__)

然后创建EchoServer类如下。这个类继承TCPServer(更多参考)。里面重写了handle_stream方法。handle_stream接收了stream和address两个参数,stream是一个iostream的object,address是client端地址。逻辑比较清晰,使用try, except来捕获io错误,如果没有错误的话,会读取stream内容直到遇到换行停止。读取到的data会写回到client端,通过write(data)。

handle_stream方法是用了@gen.coroutine装饰器和yield来实现异步读取\写回iostream。

  1. class EchoServer(TCPServer):
  2. @gen.coroutine
  3. def handle_stream(self, stream, address):
  4. while True:
  5. try:
  6. data = yield stream.read_until(b"\n")
  7. logger.info("Received bytes: %s", data)
  8. if not data.endswith(b"\n"):
  9. data = data + b"\n"
  10. yield stream.write(data)
  11. except StreamClosedError:
  12. logger.warning("Lost client at host %s", address[0])
  13. break
  14. except Exception as e:
  15. print(e)

最后在main部分,生成一个EchoServer实例并监听定义的端口,然后启动事件的ioloop。

  1. options.parse_command_line()
  2. server = EchoServer()
  3. server.listen(options.port)
  4. logger.info("Listening on TCP port %d", options.port)
  5. IOLoop.current().start()

2 Client端代码分析

  1. from __future__ import print_function
  2. from tornado.ioloop import IOLoop
  3. from tornado import gen
  4. from tornado.tcpclient import TCPClient
  5. from tornado.options import options, define
  6.  
  7. define("host", default="localhost", help="TCP server host")
  8. define("port", default=9888, help="TCP port to connect to")
  9. define("message", default="ping", help="Message to send")
  10.  
  11. @gen.coroutine
  12. def send_message():
  13. stream = yield TCPClient().connect(options.host, options.port)
  14. yield stream.write((options.message + "\n").encode())
  15. print("Sent to server:", options.message)
  16. reply = yield stream.read_until(b"\n")
  17. print("Response from server:", reply.decode().strip())
  18.  
  19. if __name__ == "__main__":
  20. options.parse_command_line()
  21. IOLoop.current().run_sync(send_message)

client.py

client 端首先定义了3个option, host,port,以及message,分别为要连接的服务端的host ip, 端口和要发送的message.

send_message用来向server端发送和接收数据。同样这里使用@gen.coroutine和yield来实现异步。

  1. @gen.coroutine
  2. def send_message():
  3. stream = yield TCPClient().connect(options.host, options.port)
  4. yield stream.write((options.message + "\n").encode())
  5. print("Sent to server:", options.message)
  6. reply = yield stream.read_until(b"\n")
  7. print("Response from server:", reply.decode().strip())

3 运行效果

server端运行后,可以使用运行client.py发送消息,发送完成后连接会端口。也可以使用telnet保持连接,交互式的发送数据给server端。

Tornado demo3 - tcpecho分析的更多相关文章

  1. tornado源码分析-iostream

    tornado源码分析-iostream 1.iostream.py作用 用来异步读写文件,socket通信 2.使用示例 import tornado.ioloop import tornado.i ...

  2. Tornado源码分析 --- 静态文件处理模块

    每个web框架都会有对静态文件的处理支持,下面对于Tornado的静态文件的处理模块的源码进行分析,以加强自己对静态文件处理的理解. 先从Tornado的主要模块 web.py 入手,可以看到在App ...

  3. Tornado源码分析系列之一: 化异步为'同步'的Future和gen.coroutine

    转自:http://blog.nathon.wang/2015/06/24/tornado-source-insight-01-gen/ 用Tornado也有一段时间,Tornado的文档还是比较匮乏 ...

  4. Tornado源码分析之http服务器篇

    转载自 http://kenby.iteye.com/blog/1159621 一. Tornado是什么? Facebook发布了开源网络服务器框架Tornado,该平台基于Facebook刚刚收购 ...

  5. tornado源码分析-模块介绍

    1.Core web framework tornado.web - web框架功能模块,包括RequestHandler和Application两个重要的类 tornado.httpserver - ...

  6. Tornado源码分析 --- Cookie和XSRF机制

    Cookie和Session的理解: 具体Cookie的介绍,可以参考:HTTP Cookie详解 可以先查看之前的一篇文章:Tornado的Cookie过期问题 XSRF跨域请求伪造(Cross-S ...

  7. Tornado源码分析 --- Redirect重定向

    “重定向”简单介绍: “重定向”指的是HTTP重定向,是HTTP协议的一种机制.当client向server发送一个请求,要求获取一个资源时,在server接收到这个请求后发现请求的这个资源实际存放在 ...

  8. Tornado源码分析 --- Etag实现

    Etag(URL的Entity Tag): 对于具体Etag是什么,请求流程,实现原理,这里不进行介绍,可以参考下面链接: http://www.oschina.net/question/234345 ...

  9. tornado源码分析系列一

    先来看一个简单的示例: #!/usr/bin/env python #coding:utf8 import socket def run(): sock = socket.socket(socket. ...

随机推荐

  1. python包的安装

    Microsoft Windows [版本 10.0.17134.228] (c) 2018 Microsoft Corporation.保留所有权利. C:\Users\Administrator& ...

  2. WIN10安装CUDA10 cuDNN

    文章目录 CPU和GPU 什么是CUDA 什么是cuDNN WIN10安装CUDA10 WIN10安装cuDNN CPU和GPU CPU和GPU是不一样的计算机设备,CPU作为计算机心脏一直被人们所认 ...

  3. Java类加载器浅述

    jdk默认提供了三种类加载器: 1.Bootstrap ClassLoader(引导类加载器): 将<JAVA_HOME>\lib目录下的类库加载到虚拟机内存中,用来加载java的核心库, ...

  4. Java 集群高可用监控(结合阿里SLB)脚本

    欢迎点评,大家一起来优化 计划思路: 只有在mysql slave java 进程状态都正常的情况下才允许nginx 运行, 否则就干掉它, 负载用的是阿里的SLB #bin/bash #邮件函数  ...

  5. 一张图轻松掌握 Flink on YARN 应用启动全流程(上)

    Flink 支持 Standalone 独立部署和 YARN.Kubernetes.Mesos 等集群部署模式,其中 YARN 集群部署模式在国内的应用越来越广泛.Flink 社区将推出 Flink ...

  6. 出现不不能引java.util.Date包的情况

    出现不不能引java.util.Date包的情况 那个时间段不能引,IDE的bug,等一会儿就好了 心得:很多时候没必要和bug死磕,因为真的不是你的问题.

  7. Laravel5.4中自定义404等错误页面

    1.在resources/views/下简历文件夹error,在error文件中建立"404.blade.php文件". <!DOCTYPE html PUBLIC &quo ...

  8. POJ-1502-MPI Maelstrom-dijkstra+输入处理

    BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distribute ...

  9. JVM规范

  10. [AHOI2014/JSOI2014]骑士游戏

    题目 思博贪心题写了一个半小时没救了,我也没看出这是一个\(spfa\)来啊 设\(dp_i\)表示彻底干掉第\(i\)只怪物的最小花费,一个非常显然的事情,就是对于\(k_i\)值最小的怪物满足\( ...