python --Tornado(异步详解)/聊天室

官文
http://demo.pythoner.com/itt2zh/ch8.html

python 原生协程示例

import requests
import asyncio


@asyncio.coroutine
def download(url):
    '''协程下载'''
    resp = requests.get(url)
    return resp.content, resp.status_code


@asyncio.coroutine     # 如果用装饰器的话 调度协程需要用 yield from
def write_file(filename, content):
    '''协程写数据'''
    with open(filename, 'wb') as f:
        f.write(content)
    print(filename, 'Write Ok')


# @asyncio.coroutine         如果不用装饰器的话用 async关键字就行(async await)
async def save(url, filename):
    '''协程保存文件'''
    print('%s 正在下载中' % url)
    await asyncio.sleep(1)
    content, code = await download(url)
    print(url, code)
    await write_file(filename, content)
    print('保存成功')


if __name__ == '__main__':
    # 获取事件循环器对象
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([
        save('https://www.baidu.com', 'baidu.html'),
        save('https://jd.com', 'jd.html'),
        save('https://mail.qq.com', 'qq_mail.html')
    ]))

Tornado发起同步请求

from tornado.web import RequestHandler
from tornado.httpclient import HTTPClient, HTTPResponse, HTTPRequest  # 框架提供发起网络请求方法(同步)



class DownloadHandler(RequestHandler):

    def get(self):
        url = self.get_query_argument('url')

        client = HTTPClient()
        response: HTTPResponse = client.fetch(url, validate_cert=False, method='POST')  # 默认为True, 改为False为不验证证书(https)
        print(response.body)  # 响应体
        print(response.code)  # 响应状态码
        print(response.headers)  # 响应头 
        
		with open('index.html', 'wb') as f:
			f.write(response.body)  # 写入文件
        self.write({'mes': '下载成功'})

注: HTTPClient 是HTTP请求的客户端类
client.fetch(request) 发送请求,request可以是str字符类的URL,也可以是HTTPRequest类对象

Tornado异步请求(长连接)

from tornado.httpclient import AsyncHTTPClient

class ....

	@tornado.web.asynchronous    # 把请求改完长连接,等待finish()结束才关闭连接
	def get(self, *args, **kwargs):
	    '''发起异步请求'''
	    client = AsyncHTTPClient()
	    client.fetch('https://www.badiu.com', callback=self.save, validate_cert=False)  # 是否验证ssl证书
		


    def save(self, response: HTTPResponse):   # 参数必须包含响应对象
        '''异步后回调的函数'''
		with open('index.html', 'wb') as f:
			f.write(response.body)

        print(response.effective_url, '下载成功')
        self.write('下载完成')
        self.finish()

Tornado异步请求(协程)

from tornado.httpclient import AsyncHTTPClient
import tornado.web
from tornado.web import gen

class ....

 
	@tornado.web.asynchronous 
	@gen.coroutione          # 可以将@gen.coroutione  改为async标识,将yield 改为await
	def get(self, *args, **kwargs):
	    '''发起异步请求'''
	    client = AsyncHTTPClient()
	    resp =  yield client.fetch('https://www.badiu.com', callback=self.save, validate_cert=False)  # 是否验证ssl证书
		self.save(response)


    def save(self, response: HTTPResponse):   # 参数必须包含响应对象
        '''异步后回调的函数'''
		with open('index.html', 'wb') as f:
			f.write(response.body)

        print(response.effective_url, '下载成功')
        self.write('下载完成')
        self.finish()

Socket(原生)

server

import socket  # 导入 socket 模块

s = socket.socket()  # 创建 socket 对象
s.bind(('127.0.0.1', 12345))  # 绑定端口

s.listen(5)  # 等待客户端连接
while True:
    c, addr = s.accept()  # 建立客户端连接
    print('连接地址:', addr)
    c.send('欢迎访问!'.encode('utf-8'))
    print(c.recv(1024).decode())
    c.close()  # 关闭

client

import socket  # 导入 socket 模块

s = socket.socket()  # 创建 socket 对象
s.connect_ex(('127.0.0.1', 12345))
print(s.recv(1024).decode('utf-8'))
s.send('ss'.encode())
s.close()

Tornado(websocket)

class EchoHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        self.write_message('connected!')

    def on_message(self, message):
        self.write_message(message)

聊天室案例

server

# coding:utf-8
import tornado.web
import tornado.ioloop
import tornado.httpserver
import tornado.options
import os
import datetime

from tornado.web import RequestHandler
from tornado.options import define, options
from tornado.websocket import WebSocketHandler

define("port", default=8000, type=int)
	
class ChatHandler(WebSocketHandler):
    users = set()  # 用来存放在线用户的容器

    def open(self):
        self.users.add(self)  # 建立连接后添加用户到容器中
        for u in self.users:  # 向已在线用户发送消息
            u.write_message(
                u"[%s]-[%s]-进入聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

    def on_message(self, message):
        print(message)
        print(self.users)
        for u in self.users:  # 向在线用户广播消息
            u.write_message(u"[%s]-[%s]-说:%s" % (
            self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message))

    def on_close(self):
        self.users.remove(self)  # 用户关闭连接后从容器中移除用户
        for u in self.users:
            u.write_message(
                u"[%s]-[%s]-离开聊天室" % (self.request.remote_ip, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))

    def check_origin(self, origin):
        return True  # 允许WebSocket的跨域请求


if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([
        (r"/ws", ChatHandler),
    ],
        debug=True
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    print('Start ws:127.0.0.1:%s' % options.port)
    tornado.ioloop.IOLoop.current().start()

html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>聊天室</title>
</head>
<body>
    <div id="contents" style="height:500px;overflow:auto;"></div>
    <div>
        <textarea id="msg"></textarea>
        <a href="javascript:;" onclick="sendMsg()">发送</a>
    </div>
<!-- jQuery -->
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        var ws = new WebSocket("ws://127.0.0.1:8000/ws");
        ws.onmessage = function(e) {
            $("#contents").append("<p>" + e.data + "</p>");
        }
        function sendMsg() {
            var msg = $("#msg").val();
            ws.send(msg);
            $("#msg").val("");
        }
    </script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像风一样的男人@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值