python制作聊天软件_Python 做 UI 超 easy!(6.2)——自制聊天工具,接收消息并 print...

之前一段时间,我们都在研究做天气预报程序,最后的成品本质上还是文本的,有的朋友问我,为什么不根据天气,展示不同的 Gif 动图啊,那样就很好用了啊!

这是一个非常好的建议,与我的想法不谋而合,但是在 PySimpleGUI 中显示图片略微复杂一些,我打算将显示图片的工作推迟到一个更适合的时候。

当下,让我们继续回到上一节的内容,发现一些更有趣的事。

上一节介绍了网络服务器的一些基本知识,IP、端口之类,希望你已经对网络通信的大体逻辑清楚了。然后用 bottle 库实现了简单的 web 服务,这是一个会根据不同姓名,向你 Say hi~ 的网页服务。

其实沿着上一节的前进方向,稍微阅读一点 bottle 的文档,很容易编写出更加复杂的 web 服务,作出类似之前天气预报一样的服务也是早晚的事,只要你真的有这个愿望,并付诸实施就一定可以。对服务器方面的开发,我作为 “引路人” 的工作到上一节就算完成了。

然而,一切并不止这么简单!魔改一下 web 服务,做个简单的聊天工具吧!像这样:

这魔改,分两步走

在网络中,各个节点是对等的,一台电脑可以同时扮演客户端和服务端。上一节已经实现了 web 服务端,它可以接受来自客户端(上一节是浏览器)发来的消息。在此基础上增加两步:

第一步,如果我们将收到的消息显示在视窗里,就是一个只能收不能发的聊天软件了。

客户端发送 Hello 给服务端的端口,这里以 HTTP 协议的默认端口 80 为例。还是使用刚认识的 bottle 库来接收客户端的数据 Hello。然后 bottle 库需要以某种方式将数据显示到视窗中的一个组件中。我们将用多行文本 Multiline,而非单行 Input 组件,以便显示多行信息记录。

这样离一个可用的聊天软件还有很大的距离,现在只能 “听”,但还是个哑巴,要是服务端能和客户端一样,向客户端发送消息就好了!

好办,第二步,我们让双方都拥有 web 服务 和 客户端功能。

任意一方都可以用自己的客户端功能,向对方的 web 服务发送消息,然后由 Multiline 组件显示在视窗中。

基建工作,从 print 开始

先从最简单的功能开始,利用 bottle 接收客户端数据,暂时用 print 打印出来,至于怎么显示在视窗上,我们稍后再介绍,这会是一个比较复杂的问题!

回顾一下上一节的代码:

from bottle import route, run, template

@route('/hello/')

def index(name):

return template('Hello {{name}}!', name=name)

run(host='localhost', port=8080)

这段代码可以让我们在自己本机浏览器中输入 *http://localhost:8080/hello/Jiangchuan*,看到包含 Hello Jiangchuan 字样的网页。这至少说明一件事:服务端知道客户端的名字 通过 @route('/hello/') 这行,bottle 库会将浏览器地址框中 hello/ 以后的字符串(比如例子里的 Jiangchuan)赋值给变量 name,在 index(name) 函数中就可以使用变量 name。

用户不会仅限于发送比如 “Jiangchuan” 之类的短词。如果我们希望客户端能向服务端传递更加复杂的消息,比如一大段文字,甚至一张照片,就不能填充在 Url(浏览器的地址栏里),毕竟地址栏就那么点地方。 web 服务的 HTTP 协议中还支持另外一种方式,便于客户端向服务端发送大数据:POST 方法。TIPS

HTTP 协议有 6 种方法:HEAD、GET、PUT、POST、DELETE、OPTIONS 等。每一种方法的数据格式都有差异,其中 POST 方法可以携带更多数据给服务端。详细介绍可以百度之。

为了方便组织信息,通常会把数据以 Json 格式组织,以类似 Python 字典的形式发给服务端处理。比如将数据这样组织:

{

"from" : "张三",

"msg” : “明天张学友演唱会门票你要么?50 一张!"

}

非常清晰,是吧!一组数据同时包含了发送者和消息。

如果你使用 Mac 或者 Linux,可以在命令行中这样提交 Json 数据:

curl -X POST -d '{"from" : "张三", "msg" : "明天张学友演唱会门票你要么?50 一张!"}' http://localhost:8080/msgTIPS:

有同学用的是 Windows,没有好用的 HTTP 调试工具,查了下很多工具都有毒。

我临时做了一个,供大家使用,项目在这里,使用方法见动图。https://github.com/JiangChuanGo/tools/tree/master/http_query​github.com

那么服务端的 bottle 库如何获得 POST 数据呢?

首先要用使用 @post('/msg') 替换 @route('/hello/'),让这个 URL 支持 POST 方法。另外我们不需要用户在 URL 中提供他的名字,他的名字直接在消息的 “from” 字段指明就好了。

然后在 index() 函数中,访问 request.body 就可以得到原始的客户端消息。如果使用 type(request.body) 会发现 request.body 是一个 BytesIO 对象,要调用它的 read 方法才能获得其中的二进制数据,再对其进行 “utf-8” 解码就能看到它的内容。

记住 request.body 中获取的数据是 Json 格式是 String,一定要用 json 库转换为 Python 字典才能直接访问。

实践一下,新建一个 recive_post_and_print.py 保存下面的代码。先完成服务端接收客户端消息的功能,就简单的把消息 print 就好了。

from bottle import route, run, template, request, post

@post('/msg')

def index():

print(request.body.read().decode("utf-8"))

return "

OK

"

run(host='localhost', port=8080)TIPS

编程有点像做雕塑,先做出一个最简单的功能,称为 MVP (minimum viable product, 最小可行产品)。 再逐步添加新功能、调整代码,逼近最终的产品。伟大的罗马城也是从最简单的土坯开始的,对吧!

我用 visual studio code 编辑这些代码,运行之后输出框中提示:

Listening on http://localhost:8080/

这说明 web 服务已经正常启动了,服务的 IP 是 localhost,端口是 8080。下来向它发送 POST 请求,如果正常的话,在输出框中可以看到发送它的消息。

我试着发送了多次消息,在输出框中都可以看到:服务器收到我的消息了。TIPS

目前,发送消息的客户端和服务器必须在同一局域网或者本机,关于网络和 IP 可以看一下上一篇文章。

那些准备知识都是有用的。

这样我们就完成第一步的一大部分了,还有个问题就是如何将消息显示到视窗中去,我们搞 PySimpleGUI 不就是为了摆脱黑框文本嘛。视窗中显示文字,不就用组件的 update 方法嘛?!

没错,但不能直接这么做。由于一些情况变得有点复杂,主要是因为:服务端不知道什么时候客户端会发送数据,可能在任意时刻;

PySimpleGUI 的 “事件循环” 是一个死循环;

bottle 为了能随时接收消息,也可以认为是一个 “事件循环“,在 run 函数中等待客户端的消息触发;

无论程序进入上述哪个循环,就意味着另一个事件循环里的逻辑永远无法执行;

所以我们会用到多线程技术,让一个程序运行多个 “事件循环”,或者说 ”死循环“。TIPS

多线程是并行计算技术之一,除此之外还有多进程、协程等技术,可以预先了解一下。

如果使用多线程技术,一个循环等待客户端的消息,一个循环在视窗中显示消息,就有下面的问题待解决:PySimpleGUI 的所有调用只能在主线程;

那就不能在 bottle 线程中更新视窗了;

只能让 bottle 收到消息,并通知视窗线程,如何做到这一点?

下一节我们会一一解决这些问题。

总结

天气预报程序先放一放,顺势搞一搞网络应用。我们制定了分两步走的计划,实现一个简单的聊天软件,目前第一步已经实现了 50%(虽然已经实现的部分占据了示意图的一大半,但真的只实现了 50% 不到),起码服务端在输出框可以打印出收到的消息了。

不用太沮丧,虽然看起来不怎么 “高端”,起码逻辑跑通了,会慢慢好起来的。

下一节会用到的新知识:多线程技术,

多线程之间的通信技术,

实时更新 PySimpleGUI 组件的方法。

明天见~

本节源码在此:https://github.com/JiangChuanGo/examples/blob/master/PySimpleGUIDemos/bottle_demo/recive_post_and_print.py​github.com

用到的调试工具在这里:https://github.com/JiangChuanGo/tools/tree/master/http_query​github.com

关注我,了解程序员的烧脑日常,还有开源的视频教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值