在这一章中,将使用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

最新文章

  1. js高阶函数
  2. [mysql]MySQL忘记密码
  3. WIN8+VS2013编写发布WCF之二(部署)
  4. MAT(1) 小样
  5. Django文档——Model中的ForeignKey,ManyToManyField与OneToOneField
  6. [简历] PHP 技能关键字列表
  7. C# Serializable学习
  8. ASP.NET MVC 学习之路-4
  9. encodeURI与decodeURI
  10. [深度学习]实现一个博弈型的AI,从五子棋开始(2)
  11. UWP 使用Telerik Grid控件
  12. [转] xgboost
  13. 记录一个pom文件
  14. React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton)
  15. Selenium&#160;win7+selenium2.0+python+JetBrains&#160;PyCharm环境搭建
  16. PAT 1064 Complete Binary Search Tree[二叉树][难]
  17. [NOI2001]炮兵阵地 【状压DP】
  18. 我的shell脚本
  19. inet_ntoa 的一个小问题
  20. #leetcode刷题之路28-实现 strStr() 函数

热门文章

  1. git设置远程仓库地址
  2. EasyMvc入门教程-基本控件说明(5)小图标
  3. Windows网络编程 2 【转】
  4. EclipseADT(4.2) 安装 STS(spring )
  5. SSH 框架搭建与开发
  6. HTML5 Canvas 绘制旋转45度佛教万字
  7. suid sgid sbit chattr lsattr find
  8. MFC中函数的使用
  9. SAS学习经验总结分享:篇五-过程步的应用
  10. 对datatable进行linq过滤