Tornado demo3 - tcpecho分析
在这个demo中,主要是使用了Tornado中异步的TCP client和server来实现一个简单的echo效果(即客户端发送的message会从server端返回到client)。代码的github链接点这里。
1 Server端代码分析
import logging
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.iostream import StreamClosedError
from tornado.tcpserver import TCPServer
from tornado.options import options, define define("port", default=9888, help="TCP port to listen on")
logger = logging.getLogger(__name__) class EchoServer(TCPServer):
@gen.coroutine
def handle_stream(self, stream, address):
while True:
try:
data = yield stream.read_until(b"\n")
logger.info("Received bytes: %s", data)
if not data.endswith(b"\n"):
data = data + b"\n"
yield stream.write(data)
except StreamClosedError:
logger.warning("Lost client at host %s", address[0])
break
except Exception as e:
print(e) if __name__ == "__main__":
options.parse_command_line()
server = EchoServer()
server.listen(options.port)
logger.info("Listening on TCP port %d", options.port)
IOLoop.current().start()
server.py
涉及到引入的模块及作用:
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用法点这里。)
define("port", default=9888, help="TCP port to listen on")
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。
class EchoServer(TCPServer):
@gen.coroutine
def handle_stream(self, stream, address):
while True:
try:
data = yield stream.read_until(b"\n")
logger.info("Received bytes: %s", data)
if not data.endswith(b"\n"):
data = data + b"\n"
yield stream.write(data)
except StreamClosedError:
logger.warning("Lost client at host %s", address[0])
break
except Exception as e:
print(e)
最后在main部分,生成一个EchoServer实例并监听定义的端口,然后启动事件的ioloop。
options.parse_command_line()
server = EchoServer()
server.listen(options.port)
logger.info("Listening on TCP port %d", options.port)
IOLoop.current().start()
2 Client端代码分析
from __future__ import print_function
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.tcpclient import TCPClient
from tornado.options import options, define define("host", default="localhost", help="TCP server host")
define("port", default=9888, help="TCP port to connect to")
define("message", default="ping", help="Message to send") @gen.coroutine
def send_message():
stream = yield TCPClient().connect(options.host, options.port)
yield stream.write((options.message + "\n").encode())
print("Sent to server:", options.message)
reply = yield stream.read_until(b"\n")
print("Response from server:", reply.decode().strip()) if __name__ == "__main__":
options.parse_command_line()
IOLoop.current().run_sync(send_message)
client.py
client 端首先定义了3个option, host,port,以及message,分别为要连接的服务端的host ip, 端口和要发送的message.
send_message用来向server端发送和接收数据。同样这里使用@gen.coroutine和yield来实现异步。
@gen.coroutine
def send_message():
stream = yield TCPClient().connect(options.host, options.port)
yield stream.write((options.message + "\n").encode())
print("Sent to server:", options.message)
reply = yield stream.read_until(b"\n")
print("Response from server:", reply.decode().strip())
3 运行效果
server端运行后,可以使用运行client.py发送消息,发送完成后连接会端口。也可以使用telnet保持连接,交互式的发送数据给server端。
最新文章
- iOS/Android 浏览器(h5)及微信中唤起本地APP
- NOI2018准备 Day9
- oracle数据库开启的时候 是先开监听还是先开主服务,关数据库的时候呢???
- android之初识Intent
- c/c++----网站及其后门(CGI应用程序)
- My SQL InnoDB 1217 - Cannot delete or update a parent row:aforeign key constraint fals
- depth_write
- LeetCode题解——Longest Palindromic Substring
- 【原】关于IPcamera几个问题的思考
- 微信下载APK
- 解决JFreeChart中文乱码问题
- -_-#【Canvas】回弹
- 将Ojective-C代码移植转换为Swift代码
- Windows phone 8 学习笔记(4) 应用的启动
- RequireJS跨域加载html模版后被转成JS问题分析及解决
- (转)linux进程 linux线程 信息查看 ps top pstree
- 使用HTML5和CSS3碎语
- HTML5和CSS3扁平化风格博客(进阶篇)
- os._exit(), sys.exit(), exit()
- Python2字符编码问题汇总