在这一章中,将使用asyncio写一个TCP服务器。这个服务器的作用是通过规范名称查找Unicode字符,来看下代码:

import asyncio

from charfinder import UnicodeNameIndex

CRLF=b'\r\n'

PROMPT=b'?>'

index=UnicodeNameIndex()

@asyncio.coroutine

def handle_queries(reader,writer):

while True:

writer.write(PROMPT)

yield from writer.drain()

data=yield from reader.readline()

try:

query=data.decode().strip()

except UnicodeDecodeError:

query='\x00'

client=writer.get_extra_info('peername')

print('Received from {}:{!r}'.format(client,query))

if query:

if ord(query[:1])<32:

break

lines=list(index.find_description_strs(query))

if lines:

writer.writelines(line.encode()+CRLF for line in lines)

writer.write(index.status(query,len(lines)).encode()+CRLF)

yield from writer.drain()

print('Sent {} results'.format(len(lines)))

print('Close the client socket')

writer.close()

def main(address='127.0.0.1',port=2323):

port=int(port)

loop=asyncio.get_event_loop()

server_coro=asyncio.start_server(handle_queries,address,port,loop=loop)

server=loop.run_until_complete(server_coro)

hosts=server.sockets[0].getsockname()

print('Serving on {}. Hit CTRL_C to stop'.format(hosts))

try:

loop.run_forever()

except KeyboardInterrupt:

pass

print('Server shutting down')

server.close()

loop.run_until_complete(server.wait_closed())

loop.close()

if __name__=="__main__":

main()

main函数的运行过程如下:

(1)在main中默认两个参数:address和port。

(2)asyncio.start_server的协程运行完后,返回的协程对象返回一个asyncio.Server实例,这个实例是一个TCP套接字服务器,封装了诸如socket函数,并且会给handle_queries传递StreamWriter.write和StreamReader.readline进行读写操作。

(3)server=loop.run_until_complete(server_coro)驱动协程,启动服务器

(4)获取这个服务器的第一个套接字的地址和端口

(5)loop.run_forever() 运行事件循环,main在这里被阻塞,直到服务器的控制台中按下CTRL-C键才会关闭

(6)最后关闭服务器,终止事件循环

来看下handle_queries的操作过程:

(1)函数接收2个参数,reader和writer,在asyncio.start_server中传递进来

(2)writer.write(PROMPT),这个其实是StreamWriter.write, 这个方法不是协程因此不能采用yield from。这个是给终端界面输出?>

(3) writer.drain刷新writer缓冲,因为它是协程,因此采用yield from

(4)yield from reader.readline()是从缓冲区读取字符,这个方法是一个协程,返回一个bytes对象

(5)writer_get_extra_info返回的是与套接字连接的远程地址

(6) 下面是输出查询到的字符到终端并在每行末尾添加了回车符和换行符

writer.writelines(line.encode()+CRLF for line in lines)

writer.write(index.status(query,len(lines)).encode()+CRLF)

(7)关闭StreamWriter流

代码运行效果如下,当输入chess black的时候会返回查询到的结果

从服务器代码中可以看到打印的如下信息

/usr/bin/python3.6 /home/zhf/py_prj/function_test/asy_server_try.py

Serving on ('127.0.0.1', 2323). Hit CTRL_C to stop

Received from ('127.0.0.1', 46670):'chess black'

Sent 6 results

流畅python学习笔记第十八章:使用asyncio编写服务器的更多相关文章

  1. 流畅python学习笔记第十八章:使用asyncio包处理并发(一)

    首先是线程与协程的对比.在文中作者通过一个实例分别采用线程实现和asynchio包实现来比较两者的差别.在多线程的样例中,会用到join的方法,下面来介绍下join方法的使用. 知识点一:当一个进程启 ...

  2. 流畅python学习笔记第十八章:使用asyncio包处理并发(二)

    前面介绍了asyncio的用法.下面我们来看下如何用协程的方式来实现之前的旋转指针的方法 @asyncio.coroutine def spin(msg): write,flush=sys.stdou ...

  3. Python学习笔记(十四)

    Python学习笔记(十四): Json and Pickle模块 shelve模块 1. Json and Pickle模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不 ...

  4. Python学习笔记(十)

    Python学习笔记(十): 装饰器的应用 列表生成式 生成器 迭代器 模块:time,random 1. 装饰器的应用-登陆练习 login_status = False # 定义登陆状态 def ...

  5. Python学习笔记(十五):类基础

    以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-24 23:59 学习笔记 1,Python中的大多 ...

  6. Python学习笔记(十四):模块高级

    以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-23 21:30 学习笔记 1,包导入是把计算机上的 ...

  7. 流畅python学习笔记:第十五章:上下文管理器

    在开始本章之前,我们首先来谈谈try-excep..final模块.在Python中,进行异常保护的最多就是用try..except..final.首先来看下下面的代码.进行一个简单的除法运算.为了防 ...

  8. 流畅python学习笔记:第十九章:动态属性和特性

    首先来看一个json文件的读取.书中给出了一个json样例.该json文件有700多K,数据量充足,适合本章的例子.文件的具体内容可以在http://www.oreilly.com/pub/sc/os ...

  9. 流畅python学习笔记:第十六章:协程

    通常在python进行编程一般都是使用多线程或者多进程来实现.这里介绍另外一种并发的方式,就是协程,但和多线程以及多进程不一样的是,协程是运行在单线程当中的并发.来看下具体的例子: def simpl ...

随机推荐

  1. 记录一次eclipse的错误:“server tomcat v7.0 server at localhost was unable to start within 45 seconds”的问题解决思路

    如果配到上述问题,可以参考网上查找的方法,如下: http://stackoverflow.com/questions/6468520/server-tomcat-v6-0-server-at-loc ...

  2. 巧用chrome开发者工具

    说明:截图中的Chrome版本为52,不同版本可能略有区别. 常用设置 开发时消除静态资源缓存不能立刻更新的困扰,勾选Disable cache即可 切换颜色显示格式 修改默认颜色显示格式,在Sett ...

  3. CSS3的box-shadow

    基础说明:     外阴影:box-shadow: X轴  Y轴  Rpx  color;     属性说明(顺序依次对应): 阴影的X轴(可以使用负值)    阴影的Y轴(可以使用负值)    阴影 ...

  4. new子类会先运行父类的构造函数

    发现子类构造函数运行时,先运行了父类的构造函数.为什么呢? 原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super(); super(): 表示父类的构造函数,并会调用于参数相对应的父类 ...

  5. 记C++课程设计--学生信息管理系统

                                                                                  C++课程设计--学生信息管理系统     ...

  6. mongodb模拟生产环境的分片集群

       分片是指数据拆分 将其分散在不同的机器上的过程,有时候也叫分区来表示这个概念.将数据分散到不同机器上 不需要功能强大的计算机就可以储存更多的数据,处理更大的负载.        几乎所有的数据库 ...

  7. 【MVC2】发布到IIS上User.Identity.Name变成空

    VS中运行时通过User.Identity.Name能取到用户名,发布到IIS上后,该值为空. 调查后发现在网站设定→[认证]中同时打开了[Windows认证]和[匿名认证], 关掉[匿名认证]后就能 ...

  8. Linux安装httpd2.4.10

    1. cd /mnt tar zxvf httpd-2.4.10.tar.gz ./configure --prefix=/mnt/apache2 --enable-dav --enable-modu ...

  9. apue学习笔记(第十五章 进程间通信)

    本章将说明进程之间相互通信的其它技术----进程间通信(IPC) 管道 管道只能在具有公共祖先的两个进程之间只用.通常,一个管道由一个进程创建,在进程调用fork后,这个管道就能在父进程和子进程之间使 ...

  10. 阿里云服务器教程–SSH 登录时出现如下错误:Host key verification failed

    注意:本文相关 Linux 配置及说明已在 CentOS 6.5 64 位操作系统中进行过测试.其它类型及版本操作系统配置可能有所差异,具体情况请参阅相应操作系统官方文档. 问题描述 使用 SSH 登 ...